diff -Nru wreport-3.6/aclocal.m4 wreport-3.15/aclocal.m4 --- wreport-3.6/aclocal.m4 2016-08-18 13:33:52.000000000 +0000 +++ wreport-3.15/aclocal.m4 2018-09-19 13:16:10.000000000 +0000 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15 -*- Autoconf -*- +# generated automatically by aclocal 1.16.1 -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,7 +20,7 @@ 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-2014 Free Software Foundation, Inc. +# Copyright (C) 2002-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -32,10 +32,10 @@ # 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.15' +[am__api_version='1.16' 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.15], [], +m4_if([$1], [1.16.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -51,14 +51,14 @@ # 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.15])dnl +[AM_AUTOMAKE_VERSION([1.16.1])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-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -110,7 +110,7 @@ # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -141,7 +141,7 @@ Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -332,13 +332,12 @@ # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 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], @@ -346,49 +345,41 @@ # Older Autoconf 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 + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_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 + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: 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 + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. Try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS @@ -397,18 +388,17 @@ # ----------------------------- # 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. +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll 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"]) -]) + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -495,8 +485,8 @@ 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 (and possibly the TAP driver). The # system "awk" is bad on some platforms. @@ -563,7 +553,7 @@ Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -605,7 +595,7 @@ done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -626,7 +616,7 @@ fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# Copyright (C) 2003-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -647,7 +637,7 @@ # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -655,49 +645,42 @@ # AM_MAKE_INCLUDE() # ----------------- -# Check to see how make treats includes. +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .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 -]) +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -738,7 +721,7 @@ # Obsolete and "removed" macros, that must however still report explicit # error messages when used, to smooth transition. # -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -765,7 +748,7 @@ # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -794,7 +777,7 @@ AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -841,7 +824,7 @@ # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -875,8 +858,11 @@ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], -[python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl - python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) +[python python2 python3 dnl + python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl + python3.2 python3.1 python3.0 dnl + python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl + python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) @@ -1076,7 +1062,7 @@ sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1095,7 +1081,7 @@ # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1176,7 +1162,7 @@ rm -f conftest.file ]) -# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# Copyright (C) 2009-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1236,7 +1222,7 @@ _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1264,7 +1250,7 @@ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# Copyright (C) 2006-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1283,7 +1269,7 @@ # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# Copyright (C) 2004-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -Nru wreport-3.6/compile wreport-3.15/compile --- wreport-3.6/compile 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/compile 2018-09-19 13:16:11.000000000 +0000 @@ -1,9 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-10-14.11; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ # 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 . +# 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 @@ -255,7 +255,8 @@ echo "compile $scriptversion" exit $? ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac @@ -339,9 +340,9 @@ # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff -Nru wreport-3.6/config.guess wreport-3.15/config.guess --- wreport-3.6/config.guess 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/config.guess 2018-09-19 13:16:11.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2016-04-02' +timestamp='2018-02-24' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ # 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 . +# 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 @@ -27,7 +27,7 @@ # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . @@ -39,7 +39,7 @@ Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2018 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." @@ -107,9 +107,9 @@ dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; + ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; @@ -132,14 +132,14 @@ UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "${UNAME_SYSTEM}" in +case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu - eval $set_cc_for_build - cat <<-EOF > $dummy.c + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc @@ -149,13 +149,20 @@ LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi ;; esac # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -169,27 +176,30 @@ # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - /sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) - arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` - machine=${arch}${endian}-unknown + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval "$set_cc_for_build" if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -205,10 +215,10 @@ ;; esac # Determine ABI tags. - case "${UNAME_MACHINE_ARCH}" in + case "$UNAME_MACHINE_ARCH" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release @@ -216,46 +226,55 @@ # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}${abi}" + echo "$machine-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:Sortix:*:*) - echo ${UNAME_MACHINE}-unknown-sortix + echo "$UNAME_MACHINE"-unknown-sortix exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -307,28 +326,19 @@ # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -340,7 +350,7 @@ echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos @@ -367,19 +377,19 @@ sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build + eval "$set_cc_for_build" SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. @@ -392,13 +402,13 @@ SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -407,25 +417,25 @@ ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -436,44 +446,44 @@ # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} + echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} + echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} + echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -482,23 +492,23 @@ #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -524,17 +534,17 @@ AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) @@ -551,7 +561,7 @@ echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -563,14 +573,14 @@ if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -581,7 +591,7 @@ exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -595,7 +605,7 @@ exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc @@ -604,18 +614,18 @@ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -630,28 +640,28 @@ echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in + case "$sc_cpu_version" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in + case "$sc_kernel_bits" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include @@ -684,13 +694,13 @@ exit (0); } EOF - (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = hppa2.0w ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + eval "$set_cc_for_build" # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -709,15 +719,15 @@ HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -742,11 +752,11 @@ exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -755,7 +765,7 @@ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -763,9 +773,9 @@ exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -790,127 +800,109 @@ echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case "$UNAME_PROCESSOR" in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; *:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) - case ${UNAME_MACHINE} in + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} + echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + echo "$UNAME_MACHINE"-pc-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -924,63 +916,63 @@ esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; k1om:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el @@ -994,64 +986,74 @@ #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; openrisc*:Linux:*:*) - echo or1k-unknown-linux-${LIBC} + echo or1k-unknown-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} + echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} + echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} + echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} + echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1065,34 +1067,34 @@ # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) @@ -1102,12 +1104,12 @@ *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1117,9 +1119,9 @@ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) @@ -1139,9 +1141,9 @@ exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1161,9 +1163,9 @@ test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; @@ -1172,28 +1174,28 @@ test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1204,7 +1206,7 @@ *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi @@ -1224,23 +1226,23 @@ exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. @@ -1259,49 +1261,56 @@ echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" exit ;; SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux${UNAME_RELEASE} + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build + eval "$set_cc_for_build" if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub @@ -1312,7 +1321,7 @@ # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` @@ -1320,19 +1329,25 @@ UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1341,7 +1356,7 @@ echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 @@ -1352,7 +1367,7 @@ else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1373,14 +1388,14 @@ echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1389,37 +1404,48 @@ echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros + echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx + echo "$UNAME_MACHINE"-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1438,16 +1464,16 @@ /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff -Nru wreport-3.6/config.sub wreport-3.15/config.sub --- wreport-3.6/config.sub 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/config.sub 2018-09-19 13:16:11.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2016-03-30' +timestamp='2018-02-22' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ # 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 . +# 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 @@ -33,7 +33,7 @@ # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -57,7 +57,7 @@ Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -67,7 +67,7 @@ version="\ GNU config.sub ($timestamp) -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2018 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." @@ -94,7 +94,7 @@ *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -112,24 +112,24 @@ # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac @@ -178,44 +178,44 @@ ;; -sco6) os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 @@ -227,10 +227,7 @@ os=-lynxos ;; -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos @@ -263,7 +260,7 @@ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ @@ -299,8 +296,9 @@ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ + | pdp10 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ @@ -314,7 +312,7 @@ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ - | we32k \ + | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown @@ -335,7 +333,7 @@ basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) ;; ms1) basic_machine=mt-unknown @@ -364,7 +362,7 @@ ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. @@ -387,7 +385,7 @@ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ @@ -428,6 +426,7 @@ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ @@ -444,6 +443,7 @@ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -457,7 +457,7 @@ # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) - basic_machine=i386-unknown + basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) @@ -491,7 +491,7 @@ basic_machine=x86_64-pc ;; amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl @@ -536,7 +536,7 @@ os=-linux ;; blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) @@ -544,13 +544,13 @@ os=-cnk ;; c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray @@ -639,10 +639,18 @@ basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -732,9 +740,6 @@ hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; - hppa-next) - os=-nextstep3 - ;; hppaosf) basic_machine=hppa1.1-hp os=-osf @@ -747,26 +752,26 @@ basic_machine=i370-ibm ;; i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; - i386-vsta | vsta) + vsta) basic_machine=i386-unknown os=-vsta ;; @@ -785,19 +790,16 @@ os=-sysv ;; leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; - m88k-omron*) - basic_machine=m88k-omron - ;; magnum | m3230) basic_machine=mips-mips os=-sysv @@ -829,10 +831,10 @@ os=-mint ;; mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k @@ -851,7 +853,7 @@ os=-msdos ;; ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc @@ -893,7 +895,7 @@ basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -938,6 +940,12 @@ nsr-tandem) basic_machine=nsr-tandem ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -970,7 +978,7 @@ os=-linux ;; parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) @@ -986,7 +994,7 @@ basic_machine=i386-pc ;; pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc @@ -1001,16 +1009,16 @@ basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould @@ -1020,23 +1028,23 @@ ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm @@ -1090,17 +1098,10 @@ sequent) basic_machine=i386-sequent ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; sh5el) basic_machine=sh5le-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) + simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -1119,7 +1120,7 @@ os=-sysv4 ;; strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun @@ -1241,6 +1242,9 @@ basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1249,20 +1253,12 @@ basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; none) basic_machine=none-none os=-none @@ -1291,10 +1287,6 @@ vax) basic_machine=vax-dec ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; pdp11) basic_machine=pdp11-dec ;; @@ -1304,9 +1296,6 @@ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; cydra) basic_machine=cydra-cydrome ;; @@ -1326,7 +1315,7 @@ # Make sure to match an already-canonicalized machine name. ;; *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac @@ -1334,10 +1323,10 @@ # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1348,8 +1337,8 @@ if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux @@ -1360,18 +1349,19 @@ -solaris) os=-solaris2 ;; - -svr4*) - os=-sysv4 - ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ @@ -1381,25 +1371,26 @@ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos*) + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1416,12 +1407,12 @@ -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc @@ -1430,10 +1421,10 @@ os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition @@ -1444,12 +1435,6 @@ -wince*) os=-wince ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; -utek*) os=-bsd ;; @@ -1474,7 +1459,7 @@ -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1496,7 +1481,7 @@ -oss*) os=-sysv3 ;; - -svr4) + -svr4*) os=-sysv4 ;; -svr3) @@ -1511,24 +1496,28 @@ -ose*) os=-ose ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; - -aros*) - os=-aros - ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; -nacl*) ;; -ios) @@ -1538,7 +1527,7 @@ *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1628,12 +1617,12 @@ sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; - *-haiku) - os=-haiku - ;; *-ibm) os=-aix ;; @@ -1673,7 +1662,7 @@ m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1688,9 +1677,6 @@ i370-*) os=-mvs ;; - *-next) - os=-nextstep3 - ;; *-gould) os=-sysv ;; @@ -1800,15 +1786,15 @@ vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$basic_machine$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff -Nru wreport-3.6/configure wreport-3.15/configure --- wreport-3.6/configure 2016-08-18 13:33:53.000000000 +0000 +++ wreport-3.15/configure 2018-09-19 13:16:11.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for wreport 3.6. +# Generated by GNU Autoconf 2.69 for wreport 3.15. # # Report bugs to . # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='wreport' PACKAGE_TARNAME='wreport' -PACKAGE_VERSION='3.6' -PACKAGE_STRING='wreport 3.6' +PACKAGE_VERSION='3.15' +PACKAGE_STRING='wreport 3.15' PACKAGE_BUGREPORT='enrico@enricozini.org' PACKAGE_URL='' @@ -662,7 +662,8 @@ LUA_LIBS LUA_CFLAGS PKG_CONFIG -DEP_LIBS +PKGCONFIG_REQUIRES +PKGCONFIG_LIBS have_doxygen FILE_OFFSET_BITS_64_FALSE FILE_OFFSET_BITS_64_TRUE @@ -703,7 +704,6 @@ AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE -am__quote am__include DEPDIR OBJEXT @@ -787,7 +787,8 @@ PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR -SHELL' +SHELL +am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking @@ -1374,7 +1375,7 @@ # 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 wreport 3.6 to adapt to many kinds of systems. +\`configure' configures wreport 3.15 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1445,7 +1446,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of wreport 3.6:";; + short | recursive ) echo "Configuration of wreport 3.15:";; esac cat <<\_ACEOF @@ -1567,7 +1568,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -wreport configure 3.6 +wreport configure 3.15 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2166,7 +2167,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by wreport $as_me 3.6, which was +It was created by wreport $as_me 3.15, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2515,7 +2516,7 @@ -am__api_version='1.15' +am__api_version='1.16' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -3030,7 +3031,7 @@ # Define the identity of the package. PACKAGE='wreport' - VERSION='3.6' + VERSION='3.15' cat >>confdefs.h <<_ACEOF @@ -3060,8 +3061,8 @@ # 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 (and possibly the TAP driver). The @@ -3112,7 +3113,7 @@ Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -3296,45 +3297,45 @@ ac_config_commands="$ac_config_commands depfiles" - -am_make=${MAKE-make} -cat > confinc << 'END' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .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 +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : @@ -13052,7 +13053,7 @@ # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no @@ -13544,7 +13545,7 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then @@ -13609,7 +13610,7 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then @@ -13948,7 +13949,7 @@ # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support @@ -14032,7 +14033,7 @@ # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. @@ -14043,7 +14044,7 @@ # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' @@ -17575,7 +17576,7 @@ FILE_OFFSET_BITS_64= if test $ac_cv_sys_file_offset_bits = 64 then - FILE_OFFSET_BITS_64=yes + FILE_OFFSET_BITS_64=yes fi if test x"$FILE_OFFSET_BITS_64" = x"yes"; then FILE_OFFSET_BITS_64_TRUE= @@ -18499,7 +18500,9 @@ fi fi -DEP_LIBS="" +PKGCONFIG_LIBS="-lm" +PKGCONFIG_REQUIRES="" + @@ -18701,6 +18704,7 @@ $as_echo "yes" >&6; } : fi + PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES lua5.2" else if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.1\""; } >&5 @@ -18785,6 +18789,7 @@ $as_echo "yes" >&6; } : fi + PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES lua5.1 >= 5.1.1" else if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua\""; } >&5 @@ -18808,12 +18813,12 @@ pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" else if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua\""; } >&5 - ($PKG_CONFIG --exists --print-errors "lua") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$PKGCONFIG_LUA_MODULE\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$PKGCONFIG_LUA_MODULE") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua" 2>/dev/null` + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "$PKGCONFIG_LUA_MODULE" 2>/dev/null` else pkg_failed=yes fi @@ -18826,12 +18831,12 @@ pkg_cv_LUA_LIBS="$LUA_LIBS" else if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua\""; } >&5 - ($PKG_CONFIG --exists --print-errors "lua") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$PKGCONFIG_LUA_MODULE\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$PKGCONFIG_LUA_MODULE") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua" 2>/dev/null` + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "$PKGCONFIG_LUA_MODULE" 2>/dev/null` else pkg_failed=yes fi @@ -18850,9 +18855,9 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "lua"` + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$PKGCONFIG_LUA_MODULE"` else - LUA_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "lua"` + LUA_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$PKGCONFIG_LUA_MODULE"` fi # Put the nasty error message in config.log where it belongs echo "$LUA_PKG_ERRORS" >&5 @@ -18869,6 +18874,7 @@ $as_echo "yes" >&6; } : fi + PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES lua >= 5.1.1" else have_lua=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua_gettop in -llua" >&5 @@ -18923,6 +18929,7 @@ LUA_CFLAGS= LUA_LIBS="-llua" + PKGCONFIG_LIBS="$PKGCONFIG_LIBS $LUA_LIBS" fi fi fi @@ -18931,7 +18938,6 @@ $as_echo "#define HAVE_LUA 1" >>confdefs.h - DEP_LIBS="$DEP_LIBS $LUA_LIBS" fi if test x"$have_lua" = x"yes"; then LUA_TRUE= @@ -18952,7 +18958,7 @@ # Find any Python interpreter. if test -z "$PYTHON"; then - for ac_prog in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 + for ac_prog in python python2 python3 python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -19154,7 +19160,7 @@ fi if test x$enable_python = xyes then - PYTHON_CFLAGS=`unset CFLAGS; $PYTHON-config --cflags` + PYTHON_CFLAGS=`unset CFLAGS; $PYTHON-config --cflags` $as_echo "#define HAVE_PYTHON /**/" >>confdefs.h @@ -19883,7 +19889,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by wreport $as_me 3.6, which was +This file was extended by wreport $as_me 3.15, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -19949,7 +19955,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -wreport config.status 3.6 +wreport config.status 3.15 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -20068,7 +20074,7 @@ # # INIT-COMMANDS # -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout @@ -21070,29 +21076,35 @@ # Older Autoconf 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 + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_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 + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: 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 -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -21110,53 +21122,48 @@ 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\(\/\/\)[^/].*/{ + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } - /^X\(\/\/\)$/{ + /^X\/\(\/\/\)$/{ s//\1/ q } - /^X\(\/\).*/{ + /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? done + if test $am_rc -ne 0; 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 $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. Try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk } ;; "libtool":C) @@ -21174,7 +21181,6 @@ cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. diff -Nru wreport-3.6/configure.ac wreport-3.15/configure.ac --- wreport-3.6/configure.ac 2016-08-18 13:31:25.000000000 +0000 +++ wreport-3.15/configure.ac 2018-09-19 13:12:11.000000000 +0000 @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(wreport, [3.6], [enrico@enricozini.org]) +AC_INIT(wreport, [3.15], [enrico@enricozini.org]) AC_CONFIG_SRCDIR([configure.ac]) AM_INIT_AUTOMAKE([foreign subdir-objects]) AC_CONFIG_HEADER(config.h) @@ -14,25 +14,25 @@ AM_PROG_LIBTOOL AC_ARG_ENABLE([docs], - [AS_HELP_STRING( - [--enable-docs], - [enable building of the documentation])], - [], - [enable_docs="yes"]) + [AS_HELP_STRING( + [--enable-docs], + [enable building of the documentation])], + [], + [enable_docs="yes"]) AC_ARG_ENABLE([doxy-undoc-warnings], - [AS_HELP_STRING( - [--enable-doxy-undoc-warnings], - [enable building of the documentation])], - [], - [enable_doxy_undoc_warnings="no"]) + [AS_HELP_STRING( + [--enable-doxy-undoc-warnings], + [enable building of the documentation])], + [], + [enable_doxy_undoc_warnings="no"]) AC_ARG_ENABLE([python], - [AS_HELP_STRING( - [--enable-python], - [build Python bindings])], - [], - [enable_python="yes"]) + [AS_HELP_STRING( + [--enable-python], + [build Python bindings])], + [], + [enable_python="yes"]) dnl To use subdirs AC_PROG_MAKE_SET @@ -52,7 +52,7 @@ FILE_OFFSET_BITS_64= if test $ac_cv_sys_file_offset_bits = 64 then - FILE_OFFSET_BITS_64=yes + FILE_OFFSET_BITS_64=yes fi AM_CONDITIONAL([FILE_OFFSET_BITS_64], [test x"$FILE_OFFSET_BITS_64" = x"yes"]) @@ -83,24 +83,29 @@ fi fi -DEP_LIBS="" -AC_SUBST(DEP_LIBS) +PKGCONFIG_LIBS="-lm" +PKGCONFIG_REQUIRES="" +AC_SUBST(PKGCONFIG_LIBS) +AC_SUBST(PKGCONFIG_REQUIRES) dnl Check for lua PKG_CHECK_EXISTS([lua5.2], [have_lua=yes], [have_lua=no]) if test x$have_lua = xyes then - PKG_CHECK_MODULES(LUA,lua5.2,,[have_lua=no]) + PKG_CHECK_MODULES(LUA,lua5.2,,[have_lua=no]) + PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES lua5.2" else PKG_CHECK_EXISTS([lua5.1], [have_lua=yes], [have_lua=no]) if test x$have_lua = xyes then PKG_CHECK_MODULES(LUA,lua5.1,,[have_lua=no]) + PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES lua5.1 >= 5.1.1" else PKG_CHECK_EXISTS([lua], [have_lua=yes], [have_lua=no]) if test x$have_lua = xyes then - PKG_CHECK_MODULES(LUA,lua,,[have_lua=no]) + PKG_CHECK_MODULES(LUA,[$PKGCONFIG_LUA_MODULE],,[have_lua=no]) + PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES lua >= 5.1.1" else dnl We don't always have the luxury of .pc files for lua, it seems have_lua=yes @@ -108,27 +113,27 @@ AC_CHECK_HEADER([lua.h], [true], [have_lua=no]) LUA_CFLAGS= LUA_LIBS="-llua" + PKGCONFIG_LIBS="$PKGCONFIG_LIBS $LUA_LIBS" fi fi fi if test x$have_lua = xyes then - AC_DEFINE([HAVE_LUA], 1, [lua is available]) - DEP_LIBS="$DEP_LIBS $LUA_LIBS" + AC_DEFINE([HAVE_LUA], 1, [lua is available]) fi AM_CONDITIONAL([LUA], [test x"$have_lua" = x"yes"]) dnl Check for python if test x$enable_python = xyes then - dnl Check for python - AM_PATH_PYTHON([], [], [enable_python=no]) + dnl Check for python + AM_PATH_PYTHON([], [], [enable_python=no]) fi if test x$enable_python = xyes then - PYTHON_CFLAGS=`unset CFLAGS; $PYTHON-config --cflags` - AC_SUBST(PYTHON_CFLAGS) - AC_DEFINE(HAVE_PYTHON,[],[Have Python bindings]) + PYTHON_CFLAGS=`unset CFLAGS; $PYTHON-config --cflags` + AC_SUBST(PYTHON_CFLAGS) + AC_DEFINE(HAVE_PYTHON,[],[Have Python bindings]) fi AM_CONDITIONAL([PYTHON], [test x"$enable_python" = x"yes"]) Binary files /tmp/tmpQffHEU/ARzBTavm6x/wreport-3.6/.copr.enc and /tmp/tmpQffHEU/c4GyE17mSb/wreport-3.15/.copr.enc differ diff -Nru wreport-3.6/debian/changelog wreport-3.15/debian/changelog --- wreport-3.6/debian/changelog 2018-06-28 12:37:34.000000000 +0000 +++ wreport-3.15/debian/changelog 2018-09-19 13:12:56.000000000 +0000 @@ -1,20 +1,31 @@ -wreport (3.6-1build3) cosmic; urgency=medium +wreport (3.15-1) unstable; urgency=medium - * No-change rebuild to build for python3.7. + * New upstream version + - Fixed Lua dependencies in generated pkg-config file + - Reverted a unit test check that got in by mistake - -- Matthias Klose Thu, 28 Jun 2018 12:37:34 +0000 + -- Enrico Zini Wed, 19 Sep 2018 15:12:56 +0200 -wreport (3.6-1build2) artful; urgency=medium +wreport (3.14-1) unstable; urgency=medium - * No-change rebuild to build to drop python3.5. + * New upstream version + - Fixed parallel build of documentation. Closes: #904714 - -- Matthias Klose Sat, 05 Aug 2017 16:28:23 +0000 + -- Enrico Zini Wed, 19 Sep 2018 14:13:57 +0200 -wreport (3.6-1build1) artful; urgency=medium +wreport (3.13-1) unstable; urgency=medium - * Rebuild for python 3.6 support. + * New upstream version - -- Bhavani Shankar Sat, 13 May 2017 19:40:51 +0530 + -- Enrico Zini Thu, 26 Jul 2018 20:54:17 +0800 + +wreport (3.12-1) unstable; urgency=medium + + * New upstream version + * Remove absolute paths from doxygen tags file, thanks Chris Lamb for the + patch. Closes: #890487 + + -- Enrico Zini Wed, 25 Jul 2018 09:42:00 +0800 wreport (3.6-1) unstable; urgency=medium diff -Nru wreport-3.6/debian/compat wreport-3.15/debian/compat --- wreport-3.6/debian/compat 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/debian/compat 2018-07-25 01:41:35.000000000 +0000 @@ -1 +1 @@ -9 +10 diff -Nru wreport-3.6/debian/control wreport-3.15/debian/control --- wreport-3.6/debian/control 2016-08-18 13:32:18.000000000 +0000 +++ wreport-3.15/debian/control 2018-07-25 01:51:48.000000000 +0000 @@ -3,12 +3,13 @@ Priority: optional Maintainer: Enrico Zini Build-Depends: - debhelper (>= 9), dh-buildinfo, dh-autoreconf, dh-python, + debhelper (>= 10), dh-buildinfo, dh-python, doxygen, pkg-config, liblua5.1-0-dev, python-all-dev, python3-all-dev, python-docutils, python-numpy, python3-numpy, python-six, python3-six -Standards-Version: 3.9.8.0 +Standards-Version: 4.1.5 +Rules-Requires-Root: no Homepage: https://github.com/ARPA-SIMC/wreport Vcs-Git: https://github.com/ARPA-SIMC/wreport.git diff -Nru wreport-3.6/debian/copyright wreport-3.15/debian/copyright --- wreport-3.6/debian/copyright 2015-11-02 10:39:50.000000000 +0000 +++ wreport-3.15/debian/copyright 2018-07-25 01:33:30.000000000 +0000 @@ -1,7 +1,7 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: wreport Upstream-Contact: Enrico Zini -Source: http://sourceforge.net/projects/wreport/ +Source: https://github.com/ARPA-SIMC/wreport/ Files: * Copyright: (C) 2005--2015 ARPA-SIM diff -Nru wreport-3.6/debian/docs wreport-3.15/debian/docs --- wreport-3.6/debian/docs 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/debian/docs 2017-12-06 14:02:40.000000000 +0000 @@ -1 +1 @@ -README +README.md diff -Nru wreport-3.6/debian/libwreport-dev.docs wreport-3.15/debian/libwreport-dev.docs --- wreport-3.6/debian/libwreport-dev.docs 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/debian/libwreport-dev.docs 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -debian/tmp/usr/share/doc/wreport/libwreport.doxytags diff -Nru wreport-3.6/debian/libwreport-doc.docs wreport-3.15/debian/libwreport-doc.docs --- wreport-3.6/debian/libwreport-doc.docs 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/debian/libwreport-doc.docs 2017-12-06 14:15:58.000000000 +0000 @@ -1 +1,2 @@ debian/tmp/usr/share/doc/wreport/apidocs +debian/tmp/usr/share/doc/wreport/libwreport.doxytags diff -Nru wreport-3.6/debian/rules wreport-3.15/debian/rules --- wreport-3.6/debian/rules 2015-11-02 10:20:37.000000000 +0000 +++ wreport-3.15/debian/rules 2018-07-25 01:26:47.000000000 +0000 @@ -26,6 +26,9 @@ done # Remove python modules .la files rm -f debian/tmp/usr/lib/python*/dist-packages/*.la + # Remove absolute build path from tag file, resulting in . + sed -i -e 's@$(CURDIR)@/usr/include@g' \ + debian/tmp/usr/share/doc/wreport/libwreport.doxytags vercheck: debian/vercheck > /dev/null diff -Nru wreport-3.6/depcomp wreport-3.15/depcomp --- wreport-3.6/depcomp 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/depcomp 2018-09-19 13:16:11.000000000 +0000 @@ -1,9 +1,9 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2013-05-30.07; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2018 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 @@ -16,7 +16,7 @@ # 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 . +# 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 @@ -783,9 +783,9 @@ # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff -Nru wreport-3.6/doc/20160914-american-fuzzy-lop.txt wreport-3.15/doc/20160914-american-fuzzy-lop.txt --- wreport-3.6/doc/20160914-american-fuzzy-lop.txt 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/doc/20160914-american-fuzzy-lop.txt 2018-07-25 01:43:44.000000000 +0000 @@ -0,0 +1,38 @@ +American Fuzzy Lop run that ended on 2016-09-14: + +Setup: + + CXX=/usr/bin/afl-g++ ./configure --disable-shared + make AFL_HARDEN=1 + afl-cmin -i testdata/bufr/ -o afl-bufr -- src/afl-test @@ + afl-fuzz -t 100 -i afl-bufr -o afl-bufr-out src/afl-test @@ + +Output + + american fuzzy lop 2.04b (afl-test) + +┌─ process timing ─────────────────────────────────────┬─ overall results ─────┐ +│ run time : 12 days, 19 hrs, 15 min, 25 sec │ cycles done : 346 │ +│ last new path : 10 days, 16 hrs, 55 min, 28 sec │ total paths : 55 │ +│ last uniq crash : none seen yet │ uniq crashes : 0 │ +│ last uniq hang : 1 days, 6 hrs, 0 min, 33 sec │ uniq hangs : 27 │ +├─ cycle progress ────────────────────┬─ map coverage ─┴───────────────────────┤ +│ now processing : 42 (76.36%) │ map density : 379 (0.58%) │ +│ paths timed out : 0 (0.00%) │ count coverage : 1.42 bits/tuple │ +├─ stage progress ────────────────────┼─ findings in depth ────────────────────┤ +│ now trying : splice 1 │ favored paths : 25 (45.45%) │ +│ stage execs : 291/750 (38.80%) │ new edges on : 30 (54.55%) │ +│ total execs : 161M │ total crashes : 0 (0 unique) │ +│ exec speed : 147.8/sec │ total hangs : 749 (27 unique) │ +├─ fuzzing strategy yields ───────────┴───────────────┬─ path geometry ────────┤ +│ bit flips : 13/171k, 2/171k, 0/171k │ levels : 5 │ +│ byte flips : 0/21.4k, 0/2094, 0/2177 │ pending : 0 │ +│ arithmetics : 2/114k, 0/75.5k, 0/34.1k │ pend fav : 0 │ +│ known ints : 0/8810, 4/43.2k, 0/82.2k │ own finds : 41 │ +│ dictionary : 0/0, 0/0, 0/18.0k │ imported : n/a │ +│ havoc : 15/56.9M, 5/103M │ variable : 0 │ +│ trim : 20.85%/9088, 89.91% ├────────────────────────┘ +└─────────────────────────────────────────────────────┘ [cpu:102%] + + +One of the hangs is a genuine bug: id:000019,src:000048+000024,op:splice,rep:8 diff -Nru wreport-3.6/doc/libwreport.dox wreport-3.15/doc/libwreport.dox --- wreport-3.6/doc/libwreport.dox 2016-08-18 13:40:22.000000000 +0000 +++ wreport-3.15/doc/libwreport.dox 2018-09-19 13:16:17.000000000 +0000 @@ -31,7 +31,7 @@ # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 3.6 +PROJECT_NUMBER = 3.15 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff -Nru wreport-3.6/doc/Makefile.am wreport-3.15/doc/Makefile.am --- wreport-3.6/doc/Makefile.am 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/doc/Makefile.am 2018-09-19 10:39:38.000000000 +0000 @@ -22,14 +22,20 @@ mainpages = ../wreport/main.dox ../wreport/style.dox ../wreport/features.dox -libwreport.doxytags apidocs/index.html: $(cdoxdeps) $(mainpages) +# See https://stackoverflow.com/questions/19822435/multiple-targets-from-one-recipe-and-parallel-execution#19822767 +.INTERMEDIATE: doxygen-run + +doxygen-run: $(cdoxdeps) $(mainpages) @test $(DOXYGEN_WARN_IF_UNDOCUMENTED) = NO && \ echo "No doxygen warnings about undocumented functions. Use ./configure --enable-doxy-undoc-warnings to turn them on" \ || true doxygen $< + +libwreport.doxytags: doxygen-run +apidocs/index.html: doxygen-run endif -EXTRA_DIST = libwreport.dox examples +EXTRA_DIST = libwreport.dox examples 20160914-american-fuzzy-lop.txt CLEANFILES = libwreport.doxytags diff -Nru wreport-3.6/doc/Makefile.in wreport-3.15/doc/Makefile.in --- wreport-3.6/doc/Makefile.in 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/doc/Makefile.in 2018-09-19 13:16:11.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -177,7 +177,6 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DEP_LIBS = @DEP_LIBS@ DLLTOOL = @DLLTOOL@ DOXYGEN_WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@ DSYMUTIL = @DSYMUTIL@ @@ -224,6 +223,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_LIBS = @PKGCONFIG_LIBS@ +PKGCONFIG_REQUIRES = @PKGCONFIG_REQUIRES@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ @@ -305,7 +306,7 @@ doc_DATA = $(am__append_1) noinst_DATA = $(am__append_2) @DO_DOCS_TRUE@mainpages = ../wreport/main.dox ../wreport/style.dox ../wreport/features.dox -EXTRA_DIST = libwreport.dox examples +EXTRA_DIST = libwreport.dox examples 20160914-american-fuzzy-lop.txt CLEANFILES = libwreport.doxytags all: all-am @@ -327,8 +328,8 @@ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -375,7 +376,10 @@ cscope cscopelist: -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -443,8 +447,8 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -@DO_DOCS_FALSE@install-data-local: @DO_DOCS_FALSE@uninstall-local: +@DO_DOCS_FALSE@install-data-local: clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am @@ -538,12 +542,18 @@ @DO_DOCS_TRUE@uninstall-local: @DO_DOCS_TRUE@ rm -rf $(DESTDIR)$(docdir)/apidocs -@DO_DOCS_TRUE@libwreport.doxytags apidocs/index.html: $(cdoxdeps) $(mainpages) +# See https://stackoverflow.com/questions/19822435/multiple-targets-from-one-recipe-and-parallel-execution#19822767 +@DO_DOCS_TRUE@.INTERMEDIATE: doxygen-run + +@DO_DOCS_TRUE@doxygen-run: $(cdoxdeps) $(mainpages) @DO_DOCS_TRUE@ @test $(DOXYGEN_WARN_IF_UNDOCUMENTED) = NO && \ @DO_DOCS_TRUE@ echo "No doxygen warnings about undocumented functions. Use ./configure --enable-doxy-undoc-warnings to turn them on" \ @DO_DOCS_TRUE@ || true @DO_DOCS_TRUE@ doxygen $< +@DO_DOCS_TRUE@libwreport.doxytags: doxygen-run +@DO_DOCS_TRUE@apidocs/index.html: doxygen-run + clean-local: rm -rf apidocs diff -Nru wreport-3.6/fabfile.py wreport-3.15/fabfile.py --- wreport-3.6/fabfile.py 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/fabfile.py 2016-09-29 13:32:06.000000000 +0000 @@ -0,0 +1,101 @@ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals +from fabric.api import local, run, sudo, cd, env, hosts, shell_env +from fabric.contrib.files import exists +import git +import re +from six.moves import shlex_quote + +env.hosts = ["venti", "ventiquattro"] +env.use_ssh_config = True + +def cmd(*args): + return " ".join(shlex_quote(a) for a in args) + +@hosts("venti") +def test_venti(): + fedora_cxxflags = "-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong"\ + " --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic" + fedora_ldflags = "-Wl,-z,relro" + + repo = git.Repo() + remote = repo.remote("venti") + push_url = remote.config_reader.get("url") + remote_dir = re.sub(r"^ssh://[^/]+", "", push_url) + + local(cmd("git", "push", "venti", "HEAD")) + with cd(remote_dir): + run(cmd("git", "checkout", "-B", "test_venti", repo.head.commit.hexsha)) + run(cmd("git", "reset", "--hard")) + run(cmd("git", "clean", "-fx")) + run(cmd("autoreconf", "-if")) + run(cmd("./configure", + "--build=x86_64-redhat-linux-gnu", + "--host=x86_64-redhat-linux-gnu", + "--program-prefix=", + "--prefix=/usr", + "--exec-prefix=/usr", + "--bindir=/usr/bin", + "--sbindir=/usr/sbin", + "--sysconfdir=/etc", + "--datadir=/usr/share", + "--includedir=/usr/include", + "--libdir=/usr/lib64", + "--libexecdir=/usr/libexec", + "--localstatedir=/var", + "--sharedstatedir=/var/lib", + "--mandir=/usr/share/man", + "--infodir=/usr/share/info", + "CFLAGS=" + fedora_cxxflags, + "CXXFLAGS=" + fedora_cxxflags, + "LDFLAGS=" + fedora_ldflags)) + run(cmd("make")) + run(cmd("make", "check")) + +@hosts("ventiquattro") +def test_ventiquattro(): + fedora_cxxflags = "-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong"\ + " --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic" + fedora_ldflags = "-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld" + + repo = git.Repo() + remote = repo.remote("ventiquattro") + push_url = remote.config_reader.get("url") + remote_dir = re.sub(r"^ssh://[^/]+", "", push_url) + + local(cmd("git", "push", "ventiquattro", "HEAD")) + with cd(remote_dir): + run(cmd("git", "checkout", "-B", "test_venti", repo.head.commit.hexsha)) + run(cmd("git", "reset", "--hard")) + run(cmd("git", "clean", "-fx")) + run(cmd("autoreconf", "-if")) + run(cmd("./configure", + "--build=x86_64-redhat-linux-gnu", + "--host=x86_64-redhat-linux-gnu", + "--program-prefix=", + "--disable-dependency-tracking", + "--prefix=/usr", + "--exec-prefix=/usr", + "--bindir=/usr/bin", + "--sbindir=/usr/sbin", + "--sysconfdir=/etc", + "--datadir=/usr/share", + "--includedir=/usr/include", + "--libdir=/usr/lib64", + "--libexecdir=/usr/libexec", + "--localstatedir=/var", + "--sharedstatedir=/var/lib", + "--mandir=/usr/share/man", + "--infodir=/usr/share/info", + "CFLAGS=" + fedora_cxxflags, + "CXXFLAGS=" + fedora_cxxflags, + "LDFLAGS=" + fedora_ldflags)) + run(cmd("make")) + run(cmd("make", "check")) + + +def test(): + test_venti() + test_ventiquattro() diff -Nru wreport-3.6/fedora/SPECS/wreport.spec wreport-3.15/fedora/SPECS/wreport.spec --- wreport-3.6/fedora/SPECS/wreport.spec 2016-08-18 13:30:03.000000000 +0000 +++ wreport-3.15/fedora/SPECS/wreport.spec 2018-09-19 13:12:11.000000000 +0000 @@ -1,13 +1,27 @@ -Summary: Library for working with (coded) weather reports +%global releaseno 1 + Name: wreport -Version: 3.5 -Release: 1 +Version: 3.15 +Release: %{releaseno}%{?dist} License: GPL2 -Group: Applications/Meteo -URL: http://www.arpa.emr.it/dettaglio_documento.asp?id=514&idlivello=64 -Source0: https://github.com/arpa-simc/%{name}/archive/v%{version}-%{release}.tar.gz#/%{name}-%{version}-%{release}.tar.gz +URL: https://github.com/arpa-simc/%{name} +Source0: https://github.com/arpa-simc/%{name}/archive/v%{version}-%{releaseno}.tar.gz#/%{name}-%{version}-%{releaseno}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot -BuildRequires: doxygen, libtool, lua-devel >= 5.1.1, python-devel +%if 0%{?rhel} == 7 +%define python3_vers python34 +%else +%define python3_vers python3 +%endif + +BuildRequires: doxygen +BuildRequires: libtool +BuildRequires: pkgconfig(lua) >= 5.1.1 +BuildRequires: python2-devel +BuildRequires: %{python3_vers}-devel +BuildRequires: python2-six +BuildRequires: %{python3_vers}-six +BuildRequires: python-docutils + Summary: Tools for working with weather reports Group: Applications/Meteo Requires: lib%{name}-common @@ -82,9 +96,23 @@ This is the Python library +%package -n %{python3_vers}-%{name}3 +Summary: shared library for working with weather reports +Group: Applications/Meteo +Requires: lib%{name}3 + +%description -n %{python3_vers}-%{name}3 +libwreport is a C++ library to read and write weather reports in BUFR and CREX + formats. + + This is the Python library + %prep -%setup -q -n %{name}-%{version}-%{release} +%setup -q -n %{name}-%{version}-%{releaseno} + +rm -rf %{py3dir} +cp -a . %{py3dir} %build @@ -93,11 +121,26 @@ %configure make +pushd %{py3dir} +autoreconf -ifv +%configure PYTHON=%{__python3} +make +popd + %check make check +pushd %{py3dir} +make check +popd + %install [ "%{buildroot}" != / ] && rm -rf "%{buildroot}" + +pushd %{py3dir} +make install DESTDIR="%{buildroot}" +popd + make install DESTDIR="%{buildroot}" %clean @@ -136,17 +179,68 @@ %files -n python-%{name}3 %defattr(-,root,root,-) -%dir %{python_sitelib}/wreport -%{python_sitelib}/wreport/* -%dir %{python_sitearch} -%{python_sitearch}/*.a -%{python_sitearch}/*.la -%{python_sitearch}/*.so* +%dir %{python2_sitelib}/wreport +%{python2_sitelib}/wreport/* +%dir %{python2_sitearch} +%{python2_sitearch}/*.a +%{python2_sitearch}/*.la +%{python2_sitearch}/*.so* %doc %{_docdir}/wreport/python-wreport.html %doc %{_docdir}/wreport/python-wreport.rst + +%files -n %{python3_vers}-%{name}3 +%defattr(-,root,root,-) +%dir %{python3_sitelib}/wreport +%{python3_sitelib}/wreport/* +%dir %{python3_sitearch} +%{python3_sitearch}/*.a +%{python3_sitearch}/*.la +%{python3_sitearch}/*.so* + + %changelog +* Wed Sep 19 2018 Emanuele Di Giacomo - 3.15-1 +- Fixed luaX.Y check in configure.ac + +* Wed Sep 19 2018 Emanuele Di Giacomo - 3.14-1 +- Fixed #19 +- Fixed parallel build +- Fixed off by one bound checkings + +* Thu Jul 26 2018 Emanuele Di Giacomo - 3.13-1 +- Added stricter and more straightforward message tests + +* Thu Jun 7 2018 Daniele Branchini - 3.12-1 +- fixed #17 + +* Mon Jun 4 2018 Daniele Branchini - 3.11-1 +- fixed #16 + +* Wed Apr 18 2018 Daniele Branchini - 3.10-2 +- Deallocate storage for Var objects + +* Thu Feb 22 2018 Daniele Branchini - 3.10-1 +- Updated wobble +- Added missing newline ad the end of verbose output + +* Tue Feb 14 2017 Daniele Branchini - 3.9-1 +- Added ppt (part per thousand) conversion + +* Mon Jan 9 2017 Daniele Branchini - 3.8-2 +- Managing python namespace for CentOs 7 + +* Mon Dec 19 2016 Daniele Branchini - 3.8-1 +- Added documentation for table file formats (fixes #11) +- Splitted python2 and python3 packages (fixes #12) + +* Wed Oct 5 2016 Daniele Branchini - 3.7-1 +- fixed duplicate varaible in table +- check tables ad build times (fixes #10) +- implemented test cases with American Fuzzy Loop +- updated wobble + * Tue Sep 15 2015 Emanuele Di Giacomo - 3.2-1%{dist} - gcc 4.8.3 support (lambdas and variadic templates) - Removed every reference to libwreport-test.pc.in diff -Nru wreport-3.6/install-sh wreport-3.15/install-sh --- wreport-3.6/install-sh 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/install-sh 2018-09-19 13:16:11.000000000 +0000 @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2014-09-12.12; # UTC +scriptversion=2018-03-11.20; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -271,15 +271,18 @@ fi dst=$dst_arg - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. + # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst - dst=$dstdir/`basename "$src"` + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac dstdir_status=0 else dstdir=`dirname "$dst"` @@ -288,6 +291,11 @@ fi fi + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + obsolete_mkdir_used=false if test $dstdir_status != 0; then @@ -324,14 +332,16 @@ # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) - # $RANDOM is not portable (e.g. dash); use it when possible to - # lower collision chance + # Note that $RANDOM variable is not portable (e.g. dash); Use it + # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 - # As "mkdir -p" follows symlinks and we work in /tmp possibly; so - # create the $tmpdir first (and fail if unsuccessful) to make sure - # that nobody tries to guess the $tmpdir name. + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p' feature. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 @@ -434,8 +444,8 @@ else # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 @@ -500,9 +510,9 @@ done # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff -Nru wreport-3.6/libwreport.pc.in wreport-3.15/libwreport.pc.in --- wreport-3.6/libwreport.pc.in 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/libwreport.pc.in 2018-09-19 10:39:37.000000000 +0000 @@ -9,5 +9,6 @@ Name: libwreport Description: Weather report library Version: @VERSION@ +Requires: @PKGCONFIG_REQUIRES@ Cflags: -I${includedir} -Libs: -L${libdir} -lwreport @DEP_LIBS@ +Libs: -L${libdir} -lwreport @PKGCONFIG_LIBS@ diff -Nru wreport-3.6/ltmain.sh wreport-3.15/ltmain.sh --- wreport-3.6/ltmain.sh 2016-08-18 13:33:47.000000000 +0000 +++ wreport-3.15/ltmain.sh 2018-09-19 13:16:08.000000000 +0000 @@ -31,7 +31,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION="2.4.6 Debian-2.4.6-0.1" +VERSION="2.4.6 Debian-2.4.6-4" package_revision=2.4.6 @@ -64,7 +64,7 @@ # libraries, which are installed to $pkgauxdir. # Set a version string for this script. -scriptversion=2015-01-20.17; # UTC +scriptversion=2015-10-12.13; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 @@ -580,16 +580,16 @@ { $debug_cmd - func_quote_for_eval "$2" - eval "$1+=\\ \$func_quote_for_eval_result" + func_quote_arg pretty "$2" + eval "$1+=\\ \$func_quote_arg_result" }' else func_append_quoted () { $debug_cmd - func_quote_for_eval "$2" - eval "$1=\$$1\\ \$func_quote_for_eval_result" + func_quote_arg pretty "$2" + eval "$1=\$$1\\ \$func_quote_arg_result" } fi @@ -1091,85 +1091,181 @@ } -# func_quote_for_eval ARG... -# -------------------------- -# Aesthetically quote ARGs to be evaled later. -# This function returns two values: -# i) func_quote_for_eval_result -# double-quoted, suitable for a subsequent eval -# ii) func_quote_for_eval_unquoted_result -# has all characters that are still active within double -# quotes backslashified. -func_quote_for_eval () +# func_quote_portable EVAL ARG +# ---------------------------- +# Internal function to portably implement func_quote_arg. Note that we still +# keep attention to performance here so we as much as possible try to avoid +# calling sed binary (so far O(N) complexity as long as func_append is O(1)). +func_quote_portable () { $debug_cmd - func_quote_for_eval_unquoted_result= - func_quote_for_eval_result= - while test 0 -lt $#; do - case $1 in - *[\\\`\"\$]*) - _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; - *) - _G_unquoted_arg=$1 ;; - esac - if test -n "$func_quote_for_eval_unquoted_result"; then - func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" - else - func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + func_quote_portable_result=$2 + + # one-time-loop (easy break) + while true + do + if $1; then + func_quote_portable_result=`$ECHO "$2" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` + break fi - case $_G_unquoted_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and variable expansion - # for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_quoted_arg=\"$_G_unquoted_arg\" + # Quote for eval. + case $func_quote_portable_result in + *[\\\`\"\$]*) + case $func_quote_portable_result in + *[\[\*\?]*) + func_quote_portable_result=`$ECHO "$func_quote_portable_result" | $SED "$sed_quote_subst"` + break + ;; + esac + + func_quote_portable_old_IFS=$IFS + for _G_char in '\' '`' '"' '$' + do + # STATE($1) PREV($2) SEPARATOR($3) + set start "" "" + func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy + IFS=$_G_char + for _G_part in $func_quote_portable_result + do + case $1 in + quote) + func_append func_quote_portable_result "$3$2" + set quote "$_G_part" "\\$_G_char" + ;; + start) + set first "" "" + func_quote_portable_result= + ;; + first) + set quote "$_G_part" "" + ;; + esac + done + done + IFS=$func_quote_portable_old_IFS ;; - *) - _G_quoted_arg=$_G_unquoted_arg - ;; + *) ;; esac - - if test -n "$func_quote_for_eval_result"; then - func_append func_quote_for_eval_result " $_G_quoted_arg" - else - func_append func_quote_for_eval_result "$_G_quoted_arg" - fi - shift + break done + + func_quote_portable_unquoted_result=$func_quote_portable_result + case $func_quote_portable_result in + # double-quote args containing shell metacharacters to delay + # word splitting, command substitution 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_portable_result=\"$func_quote_portable_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 () -{ - $debug_cmd +# func_quotefast_eval ARG +# ----------------------- +# Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG', +# but optimized for speed. Result is stored in $func_quotefast_eval. +if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then + func_quotefast_eval () + { + printf -v func_quotefast_eval_result %q "$1" + } +else + func_quotefast_eval () + { + func_quote_portable false "$1" + func_quotefast_eval_result=$func_quote_portable_result + } +fi - case $1 in - *[\\\`\"]*) - _G_arg=`$ECHO "$1" | $SED \ - -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; - *) - _G_arg=$1 ;; + +# func_quote_arg MODEs ARG +# ------------------------ +# Quote one ARG to be evaled later. MODEs argument may contain zero ore more +# specifiers listed below separated by ',' character. This function returns two +# values: +# i) func_quote_arg_result +# double-quoted (when needed), suitable for a subsequent eval +# ii) func_quote_arg_unquoted_result +# has all characters that are still active within double +# quotes backslashified. Available only if 'unquoted' is specified. +# +# Available modes: +# ---------------- +# 'eval' (default) +# - escape shell special characters +# 'expand' +# - the same as 'eval'; but do not quote variable references +# 'pretty' +# - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might +# later used in func_quote to get output like: 'echo "a b"' instead of +# 'echo a\ b'. This is slower than default on some shells. +# 'unquoted' +# - produce also $func_quote_arg_unquoted_result which does not contain +# wrapping double-quotes. +# +# Examples for 'func_quote_arg pretty,unquoted string': +# +# string | *_result | *_unquoted_result +# ------------+-----------------------+------------------- +# " | \" | \" +# a b | "a b" | a b +# "a b" | "\"a b\"" | \"a b\" +# * | "*" | * +# z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\" +# +# Examples for 'func_quote_arg pretty,unquoted,expand string': +# +# string | *_result | *_unquoted_result +# --------------+---------------------+-------------------- +# z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\" +func_quote_arg () +{ + _G_quote_expand=false + case ,$1, in + *,expand,*) + _G_quote_expand=: + ;; esac - case $_G_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. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_arg=\"$_G_arg\" + case ,$1, in + *,pretty,*|*,expand,*|*,unquoted,*) + func_quote_portable $_G_quote_expand "$2" + func_quote_arg_result=$func_quote_portable_result + func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result + ;; + *) + # Faster quote-for-eval for some shells. + func_quotefast_eval "$2" + func_quote_arg_result=$func_quotefast_eval_result ;; esac +} + - func_quote_for_expand_result=$_G_arg +# func_quote MODEs ARGs... +# ------------------------ +# Quote all ARGs to be evaled later and join them into single command. See +# func_quote_arg's description for more info. +func_quote () +{ + $debug_cmd + _G_func_quote_mode=$1 ; shift + func_quote_result= + while test 0 -lt $#; do + func_quote_arg "$_G_func_quote_mode" "$1" + if test -n "$func_quote_result"; then + func_append func_quote_result " $func_quote_arg_result" + else + func_append func_quote_result "$func_quote_arg_result" + fi + shift + done } @@ -1215,8 +1311,8 @@ _G_cmd=$1 _G_fail_exp=${2-':'} - func_quote_for_expand "$_G_cmd" - eval "func_notquiet $func_quote_for_expand_result" + func_quote_arg pretty,expand "$_G_cmd" + eval "func_notquiet $func_quote_arg_result" $opt_dry_run || { eval "$_G_cmd" @@ -1241,8 +1337,8 @@ _G_fail_exp=${2-':'} $opt_quiet || { - func_quote_for_expand "$_G_cmd" - eval "func_echo $func_quote_for_expand_result" + func_quote_arg expand,pretty "$_G_cmd" + eval "func_echo $func_quote_arg_result" } $opt_dry_run || { @@ -1370,7 +1466,7 @@ #! /bin/sh # Set a version string for this script. -scriptversion=2014-01-07.03; # UTC +scriptversion=2015-10-12.13; # UTC # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 @@ -1530,6 +1626,8 @@ { $debug_cmd + _G_rc_run_hooks=false + case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook funcions.n" ;; @@ -1538,16 +1636,16 @@ eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do - eval $_G_hook '"$@"' - - # store returned options list back into positional - # parameters for next 'cmd' execution. - eval _G_hook_result=\$${_G_hook}_result - eval set dummy "$_G_hook_result"; shift + if eval $_G_hook '"$@"'; then + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + _G_rc_run_hooks=: + fi done - func_quote_for_eval ${1+"$@"} - func_run_hooks_result=$func_quote_for_eval_result + $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result } @@ -1557,10 +1655,16 @@ ## --------------- ## # In order to add your own option parsing hooks, you must accept the -# full positional parameter list in your hook function, remove any -# options that you action, and then pass back the remaining unprocessed +# full positional parameter list in your hook function, you may remove/edit +# any options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for -# 'eval'. Like this: +# 'eval'. In this case you also must return $EXIT_SUCCESS to let the +# hook's caller know that it should pay attention to +# '_result'. Returning $EXIT_FAILURE signalizes that +# arguments are left untouched by the hook and therefore caller will ignore the +# result variable. +# +# Like this: # # my_options_prep () # { @@ -1570,9 +1674,11 @@ # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' -# -# func_quote_for_eval ${1+"$@"} -# my_options_prep_result=$func_quote_for_eval_result +# # No change in '$@' (ignored completely by this hook). There is +# # no need to do the equivalent (but slower) action: +# # func_quote eval ${1+"$@"} +# # my_options_prep_result=$func_quote_result +# false # } # func_add_hook func_options_prep my_options_prep # @@ -1581,25 +1687,37 @@ # { # $debug_cmd # +# args_changed=false +# # # Note that for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in -# --silent|-s) opt_silent=: ;; +# --silent|-s) opt_silent=: +# args_changed=: +# ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift +# args_changed=: # ;; -# *) set dummy "$_G_opt" "$*"; shift; break ;; +# *) # Make sure the first unrecognised option "$_G_opt" +# # is added back to "$@", we could need that later +# # if $args_changed is true. +# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; # esac # done # -# func_quote_for_eval ${1+"$@"} -# my_silent_option_result=$func_quote_for_eval_result +# if $args_changed; then +# func_quote eval ${1+"$@"} +# my_silent_option_result=$func_quote_result +# fi +# +# $args_changed # } # func_add_hook func_parse_options my_silent_option # @@ -1611,16 +1729,32 @@ # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # -# func_quote_for_eval ${1+"$@"} -# my_option_validation_result=$func_quote_for_eval_result +# false # } # func_add_hook func_validate_options my_option_validation # -# You'll alse need to manually amend $usage_message to reflect the extra +# You'll also need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. +# func_options_finish [ARG]... +# ---------------------------- +# Finishing the option parse loop (call 'func_options' hooks ATM). +func_options_finish () +{ + $debug_cmd + + _G_func_options_finish_exit=false + if func_run_hooks func_options ${1+"$@"}; then + func_options_finish_result=$func_run_hooks_result + _G_func_options_finish_exit=: + fi + + $_G_func_options_finish_exit +} + + # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the @@ -1630,17 +1764,28 @@ { $debug_cmd - func_options_prep ${1+"$@"} - eval func_parse_options \ - ${func_options_prep_result+"$func_options_prep_result"} - eval func_validate_options \ - ${func_parse_options_result+"$func_parse_options_result"} + _G_rc_options=false - eval func_run_hooks func_options \ - ${func_validate_options_result+"$func_validate_options_result"} + for my_func in options_prep parse_options validate_options options_finish + do + if eval func_$my_func '${1+"$@"}'; then + eval _G_res_var='$'"func_${my_func}_result" + eval set dummy "$_G_res_var" ; shift + _G_rc_options=: + fi + done + + # Save modified positional parameters for caller. As a top-level + # options-parser function we always need to set the 'func_options_result' + # variable (regardless the $_G_rc_options value). + if $_G_rc_options; then + func_options_result=$_G_res_var + else + func_quote eval ${1+"$@"} + func_options_result=$func_quote_result + fi - # save modified positional parameters for caller - func_options_result=$func_run_hooks_result + $_G_rc_options } @@ -1649,9 +1794,9 @@ # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and -# needs to propogate that back to rest of this script, then the complete +# needs to propagate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before -# returning. +# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). func_hookable func_options_prep func_options_prep () { @@ -1661,10 +1806,14 @@ opt_verbose=false opt_warning_types= - func_run_hooks func_options_prep ${1+"$@"} + _G_rc_options_prep=false + if func_run_hooks func_options_prep ${1+"$@"}; then + _G_rc_options_prep=: + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result + fi - # save modified positional parameters for caller - func_options_prep_result=$func_run_hooks_result + $_G_rc_options_prep } @@ -1678,18 +1827,20 @@ func_parse_options_result= + _G_rc_parse_options=false # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. - func_run_hooks func_parse_options ${1+"$@"} - - # Adjust func_parse_options positional parameters to match - eval set dummy "$func_run_hooks_result"; shift + if func_run_hooks func_parse_options ${1+"$@"}; then + eval set dummy "$func_run_hooks_result"; shift + _G_rc_parse_options=: + fi # Break out of the loop if we already parsed every option. test $# -gt 0 || break + _G_match_parse_options=: _G_opt=$1 shift case $_G_opt in @@ -1704,7 +1855,10 @@ ;; --warnings|--warning|-W) - test $# = 0 && func_missing_arg $_G_opt && break + if test $# = 0 && func_missing_arg $_G_opt; then + _G_rc_parse_options=: + break + fi case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above @@ -1757,15 +1911,25 @@ shift ;; - --) break ;; + --) _G_rc_parse_options=: ; break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; - *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift + _G_match_parse_options=false + break + ;; esac + + $_G_match_parse_options && _G_rc_parse_options=: done - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - func_parse_options_result=$func_quote_for_eval_result + + if $_G_rc_parse_options; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + func_parse_options_result=$func_quote_result + fi + + $_G_rc_parse_options } @@ -1778,16 +1942,21 @@ { $debug_cmd + _G_rc_validate_options=false + # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" - func_run_hooks func_validate_options ${1+"$@"} + if func_run_hooks func_validate_options ${1+"$@"}; then + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result + _G_rc_validate_options=: + fi # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE - # save modified positional parameters for caller - func_validate_options_result=$func_run_hooks_result + $_G_rc_validate_options } @@ -2068,7 +2237,7 @@ compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) - version: $progname (GNU libtool) 2.4.6 + version: $progname $scriptversion Debian-2.4.6-4 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` @@ -2270,6 +2439,8 @@ nonopt= preserve_args= + _G_rc_lt_options_prep=: + # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) @@ -2293,11 +2464,18 @@ uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; + *) + _G_rc_lt_options_prep=false + ;; esac - # Pass back the list of options. - func_quote_for_eval ${1+"$@"} - libtool_options_prep_result=$func_quote_for_eval_result + if $_G_rc_lt_options_prep; then + # Pass back the list of options. + func_quote eval ${1+"$@"} + libtool_options_prep_result=$func_quote_result + fi + + $_G_rc_lt_options_prep } func_add_hook func_options_prep libtool_options_prep @@ -2309,9 +2487,12 @@ { $debug_cmd + _G_rc_lt_parse_options=false + # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do + _G_match_lt_parse_options=: _G_opt=$1 shift case $_G_opt in @@ -2386,15 +2567,22 @@ func_append preserve_args " $_G_opt" ;; - # An option not handled by this hook function: - *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"} ; shift + _G_match_lt_parse_options=false + break + ;; esac + $_G_match_lt_parse_options && _G_rc_lt_parse_options=: done + if $_G_rc_lt_parse_options; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + libtool_parse_options_result=$func_quote_result + fi - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - libtool_parse_options_result=$func_quote_for_eval_result + $_G_rc_lt_parse_options } func_add_hook func_parse_options libtool_parse_options @@ -2451,8 +2639,8 @@ } # Pass back the unparsed argument list - func_quote_for_eval ${1+"$@"} - libtool_validate_options_result=$func_quote_for_eval_result + func_quote eval ${1+"$@"} + libtool_validate_options_result=$func_quote_result } func_add_hook func_validate_options libtool_validate_options @@ -3418,8 +3606,8 @@ esac done - func_quote_for_eval "$libobj" - test "X$libobj" != "X$func_quote_for_eval_result" \ + func_quote_arg pretty "$libobj" + test "X$libobj" != "X$func_quote_arg_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" @@ -3492,8 +3680,8 @@ 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 + func_quote_arg pretty "$srcfile" + qsrcfile=$func_quote_arg_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then @@ -4096,8 +4284,8 @@ case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. - func_quote_for_eval "$nonopt" - install_prog="$func_quote_for_eval_result " + func_quote_arg pretty "$nonopt" + install_prog="$func_quote_arg_result " arg=$1 shift else @@ -4107,8 +4295,8 @@ # 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" + func_quote_arg pretty "$arg" + func_append install_prog "$func_quote_arg_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; @@ -4165,12 +4353,12 @@ esac # Aesthetically quote the argument. - func_quote_for_eval "$arg" - func_append install_prog " $func_quote_for_eval_result" + func_quote_arg pretty "$arg" + func_append install_prog " $func_quote_arg_result" if test -n "$arg2"; then - func_quote_for_eval "$arg2" + func_quote_arg pretty "$arg2" fi - func_append install_shared_prog " $func_quote_for_eval_result" + func_append install_shared_prog " $func_quote_arg_result" done test -z "$install_prog" && \ @@ -4181,8 +4369,8 @@ 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" + func_quote_arg pretty "$install_override_mode" + func_append install_shared_prog " -m $func_quote_arg_result" fi fi @@ -4478,8 +4666,8 @@ relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { - func_quote_for_expand "$relink_command" - eval "func_echo $func_quote_for_expand_result" + func_quote_arg expand,pretty "$relink_command" + eval "func_echo $func_quote_arg_result" } if eval "$relink_command"; then : else @@ -5258,7 +5446,8 @@ if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" - qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + func_quote_arg pretty "$ECHO" + qECHO=$func_quote_arg_result $ECHO "\ # A function that is used when there is no print builtin or printf. @@ -5268,7 +5457,7 @@ \$1 _LTECHO_EOF' } - ECHO=\"$qECHO\" + ECHO=$qECHO fi # Very basic option parsing. These options are (a) specific to @@ -6611,9 +6800,9 @@ 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" + func_quote_arg pretty,unquoted "$arg" + qarg=$func_quote_arg_unquoted_result + func_append libtool_args " $func_quote_arg_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then @@ -7211,9 +7400,9 @@ 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" + func_quote_arg pretty "$flag" + func_append arg " $func_quote_arg_result" + func_append compiler_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" @@ -7227,10 +7416,10 @@ 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" + func_quote_arg pretty "$flag" + func_append arg " $wl$func_quote_arg_result" + func_append compiler_flags " $wl$func_quote_arg_result" + func_append linker_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" @@ -7254,8 +7443,8 @@ # -msg_* for osf cc -msg_*) - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result ;; # Flags to be passed through unchanged, with rationale: @@ -7279,8 +7468,8 @@ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -specs=*|-fsanitize=*) - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" @@ -7301,15 +7490,15 @@ continue else # Otherwise treat like 'Some other compiler flag' below - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result fi ;; # Some other compiler flag. -* | +*) - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result ;; *.$objext) @@ -7429,8 +7618,8 @@ *) # 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 + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result ;; esac # arg @@ -9942,8 +10131,8 @@ for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? @@ -10036,8 +10225,8 @@ eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? @@ -10511,12 +10700,12 @@ 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" + func_quote_arg pretty "$var_value" + relink_command="$var=$func_quote_arg_result; export $var; $relink_command" fi done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + func_quote_arg pretty,unquoted "(cd `pwd`; $relink_command)" + relink_command=$func_quote_arg_unquoted_result fi # Only actually do things if not in dry run mode. @@ -10756,13 +10945,14 @@ 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" + func_quote_arg pretty,unquoted "$var_value" + relink_command="$var=$func_quote_arg_unquoted_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"` + func_quote_arg pretty,unquoted "$relink_command" + relink_command=$func_quote_arg_unquoted_result if test yes = "$hardcode_automatic"; then relink_command= fi diff -Nru wreport-3.6/m4/libtool.m4 wreport-3.15/m4/libtool.m4 --- wreport-3.6/m4/libtool.m4 2016-08-18 13:33:47.000000000 +0000 +++ wreport-3.15/m4/libtool.m4 2018-09-19 13:16:08.000000000 +0000 @@ -728,7 +728,6 @@ cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. @@ -6439,7 +6438,7 @@ # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no @@ -6814,7 +6813,7 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then @@ -6879,7 +6878,7 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then @@ -7218,7 +7217,7 @@ # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support @@ -7302,7 +7301,7 @@ # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. @@ -7313,7 +7312,7 @@ # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' diff -Nru wreport-3.6/Makefile.am wreport-3.15/Makefile.am --- wreport-3.6/Makefile.am 2015-11-02 10:39:50.000000000 +0000 +++ wreport-3.15/Makefile.am 2018-07-25 01:49:06.000000000 +0000 @@ -17,5 +17,6 @@ EXTRA_DIST = libwreport.pc.in run-local run-bench testenv TODO-threads \ INSTALL BENCHMARKS LICENSE README.md \ fedora/README fedora/SPECS/wreport.spec \ - python/MANIFEST.in python/setup.py + python/MANIFEST.in python/setup.py fabfile.py \ + .copr.enc .travis-build.sh .travis.yml diff -Nru wreport-3.6/Makefile.in wreport-3.15/Makefile.in --- wreport-3.6/Makefile.in 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/Makefile.in 2018-09-19 13:16:11.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -172,7 +172,7 @@ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - cscope distdir dist dist-all distcheck + cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, @@ -260,7 +260,6 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DEP_LIBS = @DEP_LIBS@ DLLTOOL = @DLLTOOL@ DOXYGEN_WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@ DSYMUTIL = @DSYMUTIL@ @@ -307,6 +306,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_LIBS = @PKGCONFIG_LIBS@ +PKGCONFIG_REQUIRES = @PKGCONFIG_REQUIRES@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ @@ -390,7 +391,8 @@ EXTRA_DIST = libwreport.pc.in run-local run-bench testenv TODO-threads \ INSTALL BENCHMARKS LICENSE README.md \ fedora/README fedora/SPECS/wreport.spec \ - python/MANIFEST.in python/setup.py + python/MANIFEST.in python/setup.py fabfile.py \ + .copr.enc .travis-build.sh .travis.yml all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -417,8 +419,8 @@ 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);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -583,7 +585,10 @@ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -648,7 +653,7 @@ ! -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 + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -674,7 +679,7 @@ @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -692,7 +697,7 @@ distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -702,7 +707,7 @@ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac diff -Nru wreport-3.6/missing wreport-3.15/missing --- wreport-3.6/missing 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/missing 2018-09-19 13:16:11.000000000 +0000 @@ -1,9 +1,9 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2013-10-28.13; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ # 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 . +# 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 @@ -101,9 +101,9 @@ exit $st fi -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software program_details () { @@ -207,9 +207,9 @@ exit $st # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff -Nru wreport-3.6/py-compile wreport-3.15/py-compile --- wreport-3.6/py-compile 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/py-compile 2018-09-19 13:16:11.000000000 +0000 @@ -1,9 +1,9 @@ #!/bin/sh # py-compile - Compile a Python program -scriptversion=2011-06-08.12; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 2000-2014 Free Software Foundation, Inc. +# Copyright (C) 2000-2018 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 @@ -16,7 +16,7 @@ # 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 . +# 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 @@ -162,9 +162,9 @@ # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff -Nru wreport-3.6/python/Makefile.in wreport-3.15/python/Makefile.in --- wreport-3.6/python/Makefile.in 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/python/Makefile.in 2018-09-19 13:16:11.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -163,7 +163,12 @@ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/_wreport_la-common.Plo \ + ./$(DEPDIR)/_wreport_la-var.Plo \ + ./$(DEPDIR)/_wreport_la-varinfo.Plo \ + ./$(DEPDIR)/_wreport_la-vartable.Plo \ + ./$(DEPDIR)/_wreport_la-wreport.Plo am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) @@ -192,7 +197,7 @@ esac am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile) am__pep3147_tweak = \ - sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|' + sed -e 's|\.py$$||' -e 's|[^/]*$$|&.*.pyc\n&.*.pyo|' py_compile = $(top_srcdir)/py-compile DATA = $(doc_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) @@ -237,7 +242,6 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DEP_LIBS = @DEP_LIBS@ DLLTOOL = @DLLTOOL@ DOXYGEN_WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@ DSYMUTIL = @DSYMUTIL@ @@ -284,6 +288,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_LIBS = @PKGCONFIG_LIBS@ +PKGCONFIG_REQUIRES = @PKGCONFIG_REQUIRES@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ @@ -402,8 +408,8 @@ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -459,11 +465,17 @@ distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-common.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-var.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-varinfo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-vartable.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-wreport.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-var.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-varinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-vartable.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_wreport_la-wreport.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -562,20 +574,15 @@ dir='$(DESTDIR)$(pkgpythondir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ - py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ - echo "$$py_files_pep3147";\ - pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ - pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ - for files in \ - "$$py_files" \ - "$$pyc_files" \ - "$$pyo_files" \ - "$$pyc_files_pep3147" \ - "$$pyo_files_pep3147" \ - ; do \ + for files in "$$py_files" "$$pyc_files" "$$pyo_files"; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ + dir='$(DESTDIR)$(pkgpythondir)/__pycache__'; \ + echo "$$py_files" | $(am__pep3147_tweak) | $(am__base_list) | \ + while read files; do \ + $(am__uninstall_files_from_dir) || st=$$?; \ + done || exit $$?; \ exit $$st install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) @@ -651,7 +658,10 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -726,7 +736,11 @@ clean-pyexecLTLIBRARIES mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/_wreport_la-common.Plo + -rm -f ./$(DEPDIR)/_wreport_la-var.Plo + -rm -f ./$(DEPDIR)/_wreport_la-varinfo.Plo + -rm -f ./$(DEPDIR)/_wreport_la-vartable.Plo + -rm -f ./$(DEPDIR)/_wreport_la-wreport.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -772,7 +786,11 @@ installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/_wreport_la-common.Plo + -rm -f ./$(DEPDIR)/_wreport_la-var.Plo + -rm -f ./$(DEPDIR)/_wreport_la-varinfo.Plo + -rm -f ./$(DEPDIR)/_wreport_la-vartable.Plo + -rm -f ./$(DEPDIR)/_wreport_la-wreport.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -794,8 +812,8 @@ .MAKE: check-am install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ - clean-generic clean-libtool clean-local \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am \ + check-local clean clean-generic clean-libtool clean-local \ clean-pyexecLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ diff -Nru wreport-3.6/python/test-var.py wreport-3.15/python/test-var.py --- wreport-3.6/python/test-var.py 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/python/test-var.py 2018-06-07 13:20:39.000000000 +0000 @@ -8,6 +8,7 @@ import unittest from six import string_types + class Var(unittest.TestCase): def setUp(self): self.table = wreport.Vartable.get_bufr(master_table_version_number=24) @@ -17,6 +18,7 @@ self.assertEqual(var.code, "B01001") self.assertEqual(var.info.code, "B01001") self.assertFalse(var.isset) + def testIntCreation(self): var = wreport.Var(self.table["B05001"], 12) self.assertEqual(var.code, "B05001") @@ -24,6 +26,7 @@ self.assertEqual(var.enqi(), 12) self.assertEqual(var.enqd(), 0.00012) self.assertEqual(var.enqc(), "12") + def testFloatCreation(self): var = wreport.Var(self.table["B05001"], 12.4) self.assertEqual(var.code, "B05001") @@ -31,6 +34,7 @@ self.assertEqual(var.enqi(), 1240000) self.assertEqual(var.enqd(), 12.4) self.assertEqual(var.enqc(), "1240000") + def testStringCreation(self): var = wreport.Var(self.table["B05001"], "123456") self.assertEqual(var.code, "B05001") @@ -38,6 +42,7 @@ self.assertEqual(var.enqi(), 123456) self.assertEqual(var.enqd(), 1.23456) self.assertEqual(var.enqc(), "123456") + def testStringification(self): var = wreport.Var(self.table["B01001"]) self.assertEqual(str(var), "None") @@ -49,6 +54,7 @@ self.assertEqual(str(var), "12.40000") self.assertEqual(repr(var), "Var('B05001', 12.40000)") self.assertEqual(var.format("foo"), "12.40000") + def testEnq(self): var = wreport.Var(self.table["B01001"], 1) self.assertEqual(type(var.enq()), int) @@ -59,6 +65,7 @@ var = wreport.Var(self.table["B01019"], "ciao") self.assertIsInstance(var.enq(), string_types) self.assertEqual(var.enq(), "ciao") + def testGet(self): var = wreport.Var(self.table["B01001"]) self.assertIsNone(var.get()) @@ -69,6 +76,7 @@ self.assertEqual(var.get(), 1.12345) var = wreport.Var(self.table["B01019"], "ciao") self.assertEqual(var.get(), "ciao") + def testEq(self): var = wreport.Var(self.table["B01001"], 1) self.assertEqual(var, var) diff -Nru wreport-3.6/python/var.cc wreport-3.15/python/var.cc --- wreport-3.6/python/var.cc 2016-01-25 15:14:02.000000000 +0000 +++ wreport-3.15/python/var.cc 2018-06-07 13:20:39.000000000 +0000 @@ -80,12 +80,14 @@ return (PyObject*)varinfo_create(self->var.info()); } +#define PYFIXME (char*) static PyGetSetDef wrpy_Var_getsetters[] = { - {"code", (getter)wrpy_Var_code, NULL, "variable code", NULL }, - {"isset", (getter)wrpy_Var_isset, NULL, "true if the value is set", NULL }, - {"info", (getter)wrpy_Var_info, NULL, "Varinfo for this variable", NULL }, + {PYFIXME "code", (getter)wrpy_Var_code, NULL, PYFIXME "variable code", NULL }, + {PYFIXME "isset", (getter)wrpy_Var_isset, NULL, PYFIXME "true if the value is set", NULL }, + {PYFIXME "info", (getter)wrpy_Var_info, NULL, PYFIXME "Varinfo for this variable", NULL }, {NULL} }; +#undef PYFIXME static PyObject* wrpy_Var_enqi(wrpy_Var* self) { @@ -113,11 +115,12 @@ return var_value_to_python(self->var); } +#define PYFIXME (char**) static PyObject* wrpy_Var_get(wrpy_Var* self, PyObject* args, PyObject* kw) { - static char* kwlist[] = { "default", NULL }; + static const char* kwlist[] = { "default", NULL }; PyObject* def = Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", kwlist, &def)) + if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", PYFIXME kwlist, &def)) return NULL; if (self->var.isset()) return var_value_to_python(self->var); @@ -130,13 +133,14 @@ static PyObject* wrpy_Var_format(wrpy_Var* self, PyObject* args, PyObject* kw) { - static char* kwlist[] = { "default", NULL }; + static const char* kwlist[] = { "default", NULL }; const char* def = ""; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|s", kwlist, &def)) + if (!PyArg_ParseTupleAndKeywords(args, kw, "|s", PYFIXME kwlist, &def)) return NULL; std::string f = self->var.format(def); return PyUnicode_FromString(f.c_str()); } +#undef PYFIXME static PyMethodDef wrpy_Var_methods[] = { {"enqi", (PyCFunction)wrpy_Var_enqi, METH_NOARGS, R"( @@ -211,6 +215,7 @@ { // Explicitly call destructor self->var.~Var(); + Py_TYPE(self)->tp_free(self); } static PyObject* wrpy_Var_str(wrpy_Var* self) diff -Nru wreport-3.6/README.md wreport-3.15/README.md --- wreport-3.6/README.md 2016-01-25 15:04:56.000000000 +0000 +++ wreport-3.15/README.md 2018-05-12 13:35:30.000000000 +0000 @@ -1,8 +1,15 @@ -WREPORT -=============================================================== +# WREPORT -Introduction ------------- +## Build status + +| Environment | Status | +| ----------- | ------ | +| CentOS 7 | [![Build Status](https://badges.herokuapp.com/travis/ARPA-SIMC/wreport?branch=master&env=DOCKER_IMAGE=centos:7&label=centos7)](https://travis-ci.org/ARPA-SIMC/wreport) | +| Fedora 26 | [![Build Status](https://badges.herokuapp.com/travis/ARPA-SIMC/wreport?branch=master&env=DOCKER_IMAGE=fedora:26&label=fedora26)](https://travis-ci.org/ARPA-SIMC/wreport) | +| Fedora 27 | [![Build Status](https://badges.herokuapp.com/travis/ARPA-SIMC/wreport?branch=master&env=DOCKER_IMAGE=fedora:27&label=fedora27)](https://travis-ci.org/ARPA-SIMC/wreport) | +| Fedora 28 | [![Build Status](https://badges.herokuapp.com/travis/ARPA-SIMC/wreport?branch=master&env=DOCKER_IMAGE=fedora:28&label=fedora28)](https://travis-ci.org/ARPA-SIMC/wreport) | + +## Introduction wreport is a C++ library for working with weather reports. @@ -19,10 +26,9 @@ - Unit conversion - Handling of physical variables -Building wreport ----------------- +## Building wreport -you need to install the automake/autoconf/libtool packages, which are usually +You need to install the automake/autoconf/libtool packages, which are usually available on any linux distribution, and, in the wreport directory, execute the commands: @@ -34,12 +40,20 @@ if you're familiar with .rpm and .deb packaging you'll find the packaging files in the `debian` and `fedora` directories -Contact and copyright information ---------------------------------- +### AFL instrumentation + +To run wreport using [American Fuzzy Lop](http://lcamtuf.coredump.cx/afl/): + + CXX=/usr/bin/afl-g++ ./configure --disable-shared + make AFL_HARDEN=1 + afl-cmin -i testdata/bufr/ -o afl-bufr -- src/afl-test @@ + afl-fuzz -t 100 -i afl-bufr -o afl-bufr-out src/afl-test @@ + +## Contact and copyright information The author of wreport is Enrico Zini -wreport is Copyright (C) 2005-2015 ARPA-SIMC +wreport is Copyright (C) 2005-2018 ARPAE-SIMC wreport is licensed under the terms of the GNU General Public License version 2. diff -Nru wreport-3.6/src/afl-test.cc wreport-3.15/src/afl-test.cc --- wreport-3.6/src/afl-test.cc 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/src/afl-test.cc 2016-08-31 12:54:59.000000000 +0000 @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include "options.h" +#include +#include +#include +#include "config.h" + +using namespace wreport; +using namespace std; + +/** + * Read a BUFR and iterate its contents, printing only errors if they happen. + * + * This can be used as a test program for AFL (see http://lcamtuf.coredump.cx/afl/ ) + */ +int main(int argc, char* argv[]) +{ + if (argc != 2) + { + fputs("Usage: afl-test file\n", stderr); + return 1; + } + + try { + // Open the input file + const char* fname = argv[1]; + FILE* in = fopen(fname, "rb"); + if (in == NULL) + error_system::throwf("opening file %s", fname); + + // Use a generic try/catch block to ensure we always close the input file, + // even in case of errors + try { + // String used to hold raw data read from the input file + string raw_data; + + // (optional) offset of the start of the BUFR message read, which we + // pass to the decoder to have nicer error messages + off_t offset; + + // Read all BUFR data in the input file, one message at a time. Extra + // data before and after each BUFR message is skipped. + // fname and offset are optional and we pass them just to have nicer + // error messages. + while (BufrBulletin::read(in, raw_data, fname, &offset)) + { + // Decode the raw data. fname and offset are optional and we pass + // them just to have nicer error messages + auto bulletin = BufrBulletin::decode_header(raw_data, fname, offset); + + for (const auto& subset: bulletin->subsets) + for (const auto& var: subset) + var.enqs(); + } + + // Cleanup + fclose(in); + } catch (...) { + fclose(in); + throw; + } + } catch (std::exception& e) { + fprintf(stderr, "%s\n", e.what()); + return 1; + } + + return 0; +} diff -Nru wreport-3.6/src/input.cc wreport-3.15/src/input.cc --- wreport-3.6/src/input.cc 2016-01-26 15:05:03.000000000 +0000 +++ wreport-3.15/src/input.cc 2018-05-14 15:34:17.000000000 +0000 @@ -36,7 +36,7 @@ // even in case of errors try { // String used to hold raw data read from the input file - string raw_data; + std::string raw_data; // (optional) offset of the start of the BUFR message read, which we // pass to the decoder to have nicer error messages diff -Nru wreport-3.6/src/Makefile.am wreport-3.15/src/Makefile.am --- wreport-3.6/src/Makefile.am 2016-01-25 15:04:56.000000000 +0000 +++ wreport-3.15/src/Makefile.am 2016-08-31 11:00:55.000000000 +0000 @@ -10,13 +10,17 @@ dist_noinst_HEADERS = options.h info.cc input.cc output.cc iterate.cc makebuoy.cc unparsable.cc bin_PROGRAMS = wrep -noinst_PROGRAMS = examples +noinst_PROGRAMS = examples afl-test dist_bin_SCRIPTS = wrep-importtable wrep_SOURCES = options.cc wrep.cc wrep_LDFLAGS = $(WREPLIBS) wrep_DEPENDENCIES = $(WREPLIBS) +afl_test_SOURCES = afl-test.cc +afl_test_LDFLAGS = $(WREPLIBS) +afl_test_DEPENDENCIES = $(WREPLIBS) + examples_SOURCES = examples.cc examples_LDFLAGS = $(WREPLIBS) examples_DEPENDENCIES = $(WREPLIBS) diff -Nru wreport-3.6/src/Makefile.in wreport-3.15/src/Makefile.in --- wreport-3.6/src/Makefile.in 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/src/Makefile.in 2018-09-19 13:16:11.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -92,7 +92,7 @@ host_triplet = @host@ @FILE_OFFSET_BITS_64_TRUE@am__append_1 = -D_FILE_OFFSET_BITS=64 bin_PROGRAMS = wrep$(EXEEXT) -noinst_PROGRAMS = examples$(EXEEXT) +noinst_PROGRAMS = examples$(EXEEXT) afl-test$(EXEEXT) subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ @@ -112,13 +112,19 @@ CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) -am_examples_OBJECTS = examples.$(OBJEXT) -examples_OBJECTS = $(am_examples_OBJECTS) -examples_LDADD = $(LDADD) +am_afl_test_OBJECTS = afl-test.$(OBJEXT) +afl_test_OBJECTS = $(am_afl_test_OBJECTS) +afl_test_LDADD = $(LDADD) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = +afl_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(afl_test_LDFLAGS) $(LDFLAGS) -o $@ +am_examples_OBJECTS = examples.$(OBJEXT) +examples_OBJECTS = $(am_examples_OBJECTS) +examples_LDADD = $(LDADD) examples_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(examples_LDFLAGS) $(LDFLAGS) -o $@ @@ -170,7 +176,9 @@ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/afl-test.Po ./$(DEPDIR)/examples.Po \ + ./$(DEPDIR)/options.Po ./$(DEPDIR)/wrep.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) @@ -190,8 +198,8 @@ am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = -SOURCES = $(examples_SOURCES) $(wrep_SOURCES) -DIST_SOURCES = $(examples_SOURCES) $(wrep_SOURCES) +SOURCES = $(afl_test_SOURCES) $(examples_SOURCES) $(wrep_SOURCES) +DIST_SOURCES = $(afl_test_SOURCES) $(examples_SOURCES) $(wrep_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -239,7 +247,6 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DEP_LIBS = @DEP_LIBS@ DLLTOOL = @DLLTOOL@ DOXYGEN_WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@ DSYMUTIL = @DSYMUTIL@ @@ -286,6 +293,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_LIBS = @PKGCONFIG_LIBS@ +PKGCONFIG_REQUIRES = @PKGCONFIG_REQUIRES@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ @@ -369,6 +378,9 @@ wrep_SOURCES = options.cc wrep.cc wrep_LDFLAGS = $(WREPLIBS) wrep_DEPENDENCIES = $(WREPLIBS) +afl_test_SOURCES = afl-test.cc +afl_test_LDFLAGS = $(WREPLIBS) +afl_test_DEPENDENCIES = $(WREPLIBS) examples_SOURCES = examples.cc examples_LDFLAGS = $(WREPLIBS) examples_DEPENDENCIES = $(WREPLIBS) @@ -393,8 +405,8 @@ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -464,6 +476,10 @@ echo " rm -f" $$list; \ rm -f $$list +afl-test$(EXEEXT): $(afl_test_OBJECTS) $(afl_test_DEPENDENCIES) $(EXTRA_afl_test_DEPENDENCIES) + @rm -f afl-test$(EXEEXT) + $(AM_V_CXXLD)$(afl_test_LINK) $(afl_test_OBJECTS) $(afl_test_LDADD) $(LIBS) + examples$(EXEEXT): $(examples_OBJECTS) $(examples_DEPENDENCIES) $(EXTRA_examples_DEPENDENCIES) @rm -f examples$(EXEEXT) $(AM_V_CXXLD)$(examples_LINK) $(examples_OBJECTS) $(examples_LDADD) $(LIBS) @@ -513,9 +529,16 @@ distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/examples.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrep.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afl-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/examples.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrep.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -599,7 +622,10 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -672,7 +698,10 @@ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/afl-test.Po + -rm -f ./$(DEPDIR)/examples.Po + -rm -f ./$(DEPDIR)/options.Po + -rm -f ./$(DEPDIR)/wrep.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -718,7 +747,10 @@ installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/afl-test.Po + -rm -f ./$(DEPDIR)/examples.Po + -rm -f ./$(DEPDIR)/options.Po + -rm -f ./$(DEPDIR)/wrep.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -739,7 +771,7 @@ .MAKE: install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ diff -Nru wreport-3.6/src/options.h wreport-3.15/src/options.h --- wreport-3.6/src/options.h 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/src/options.h 2018-05-14 15:34:17.000000000 +0000 @@ -34,6 +34,7 @@ DUMP, DUMP_STRUCTURE, DUMP_DDS, + TRACE, PRINT_VARS, INFO, UNPARSABLE, diff -Nru wreport-3.6/src/output.cc wreport-3.15/src/output.cc --- wreport-3.6/src/output.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/src/output.cc 2018-05-14 15:34:17.000000000 +0000 @@ -36,6 +36,27 @@ } }; +struct PrintTrace : public BulletinFullHandler +{ + FILE* out; + PrintTrace(FILE* out=stderr) : out(out) {} + + void handle_raw_bufr(const std::string& raw_data, const char* fname, long offset) override + { + try { + // Decode the raw data. fname and offset are optional and we pass + // them just to have nicer error messages + auto bulletin = wreport::BufrBulletin::decode_verbose(raw_data, out, fname, offset); + + // Do something with the decoded information + handle(*bulletin); + } catch (std::exception& e) { + fprintf(stderr, "%s:%ld:%s\n", fname, offset, e.what()); + } + } + void handle(wreport::Bulletin& b) override {} +}; + struct PrintStructure : public BulletinFullHandler { FILE* out; diff -Nru wreport-3.6/src/wrep.cc wreport-3.15/src/wrep.cc --- wreport-3.6/src/wrep.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/src/wrep.cc 2018-05-14 15:34:17.000000000 +0000 @@ -38,6 +38,7 @@ " -h,--help print this help message\n" " -i,--info print configuration information\n" " -d,--dump (default) dump message contents\n" + " -t,--trace print a verbose trace of the decoding process\n" " -s,--structure dump message contents and structure\n" " -D,--dds dump message Data Descriptor Section\n" " -p,--print=VARCODES for each input bulletin, print the given\n" @@ -61,6 +62,7 @@ /* These options set a flag. */ {"crex", no_argument, NULL, 'c'}, {"dump", no_argument, NULL, 'd'}, + {"trace", no_argument, NULL, 't'}, {"structure", no_argument, NULL, 's'}, {"dds", no_argument, NULL, 'D'}, {"print", required_argument, NULL, 'p'}, @@ -83,10 +85,10 @@ int option_index = 0; #ifdef HAS_GETOPT_LONG - int c = getopt_long(argc, argv, "cdsDpivUTFLh:", + int c = getopt_long(argc, argv, "cdsDpivtUTFLh:", long_options, &option_index); #else - int c = getopt(argc, argv, "cdsDpivUTFLh:"); + int c = getopt(argc, argv, "cdsDpivtUTFLh:"); #endif // Detect the end of the options @@ -98,6 +100,7 @@ case 'c': options.crex = true; break; case 'v': options.verbose = true; break; case 'd': options.action = DUMP; break; + case 't': options.action = TRACE; break; case 's': options.action = DUMP_STRUCTURE; break; case 'D': options.action = DUMP_DDS; break; case 'p': @@ -134,6 +137,7 @@ case LIST_TABLES: tabledir::Tabledirs::get().print(stdout); return 0; + case TRACE: handler.reset(new PrintTrace(stdout)); break; case DUMP: handler.reset(new PrintContents(stdout)); break; case DUMP_STRUCTURE: handler.reset(new PrintStructure(stdout)); break; case DUMP_DDS: handler.reset(new PrintDDS(stdout)); break; diff -Nru wreport-3.6/tables/B0000000000000012000.txt wreport-3.15/tables/B0000000000000012000.txt --- wreport-3.6/tables/B0000000000000012000.txt 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/tables/B0000000000000012000.txt 2016-09-29 13:37:47.000000000 +0000 @@ -242,7 +242,7 @@ 002197 SATELLITE CHANNEL CENTRE FREQUENCY Hz -8 0 26 002198 SATELLITE CHANNEL BAND WIDTH Hz -8 0 26 002199 INTEGRATED MEAN HUMIDITY COMPUTATIONAL METHOD CODE TABLE 2199 0 0 4 - 002200 LATITUDINAL RESOLUTION DEGREE 5 25 + 002200 LATITUDINAL RESOLUTION DEGREE 5 0 25 002202 SIMULATED DATA PROCESSING TECHNIQUE USED FLAG TABLE 2202 0 0 4 002220 DATA PRODUCER CODE TABLE 2220 0 0 9 002221 SEGMENT SIZE AT NADIR IN X DIRECTION M 0 0 18 diff -Nru wreport-3.6/tables/B0000000000000013000.txt wreport-3.15/tables/B0000000000000013000.txt --- wreport-3.6/tables/B0000000000000013000.txt 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/tables/B0000000000000013000.txt 2016-09-29 13:37:47.000000000 +0000 @@ -242,7 +242,7 @@ 002197 SATELLITE CHANNEL CENTRE FREQUENCY Hz -8 0 26 002198 SATELLITE CHANNEL BAND WIDTH Hz -8 0 26 002199 INTEGRATED MEAN HUMIDITY COMPUTATIONAL METHOD CODE TABLE 2199 0 0 4 - 002200 LATITUDINAL RESOLUTION DEGREE 5 25 + 002200 LATITUDINAL RESOLUTION DEGREE 5 0 25 002202 SIMULATED DATA PROCESSING TECHNIQUE USED FLAG TABLE 2202 0 0 4 002220 DATA PRODUCER CODE TABLE 2220 0 0 9 002221 SEGMENT SIZE AT NADIR IN X DIRECTION M 0 0 18 diff -Nru wreport-3.6/tables/B0000000000000014000.txt wreport-3.15/tables/B0000000000000014000.txt --- wreport-3.6/tables/B0000000000000014000.txt 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/tables/B0000000000000014000.txt 2016-09-29 13:37:47.000000000 +0000 @@ -261,8 +261,8 @@ 002197 SATELLITE CHANNEL CENTRE FREQUENCY Hz -8 0 26 002198 SATELLITE CHANNEL BAND WIDTH Hz -8 0 26 002199 INTEGRATED MEAN HUMIDITY COMPUTATIONAL METHOD CODE TABLE 2199 0 0 4 - 002200 LATITUDINAL RESOLUTION DEGREE 5 25 - 002201 LONGITUDINAL RESOLUTION DEGREE 5 25 + 002200 LATITUDINAL RESOLUTION DEGREE 5 0 25 + 002201 LONGITUDINAL RESOLUTION DEGREE 5 0 25 002202 SIMULATED DATA PROCESSING TECHNIQUE USED FLAG TABLE 2202 0 0 4 002205 LATITUDINAL RESOLUTION DEGREE 3 0 9 002206 LONGITUDINAL RESOLUTION DEGREE 3 0 9 diff -Nru wreport-3.6/tables/B0000000000000021000.txt wreport-3.15/tables/B0000000000000021000.txt --- wreport-3.6/tables/B0000000000000021000.txt 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/tables/B0000000000000021000.txt 2016-09-14 18:18:50.000000000 +0000 @@ -860,7 +860,6 @@ 020052 Amount of middle clouds % 0 0 7 % 0 3 020053 Amount of high clouds % 0 0 7 % 0 3 020054 True direction from which a phenomenon or clouds are moving DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 - 020054 True direction from which a phenomenon or clouds are moving or i DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 020055 State of sky in the tropics CODE TABLE 0 0 4 CODE TABLE 0 2 020056 Cloud phase CODE TABLE 0 0 3 CODE TABLE 0 1 020058 Visibility seawards from a coastal station M -1 0 13 M -1 4 diff -Nru wreport-3.6/tables/B000000000980601.txt wreport-3.15/tables/B000000000980601.txt --- wreport-3.6/tables/B000000000980601.txt 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/tables/B000000000980601.txt 2016-11-07 10:08:48.000000000 +0000 @@ -633,7 +633,8 @@ 013230 CONVECTIVE PRECIPITATION KG/M**2 1 -1 14 013231 LARGE SCALE PRECIPITATION KG/M**2 1 -1 14 013233 FRACTION OF TOTAL PRECIPITATION IN SOLID FORM (SNOW) M 4 0 18 - 013240 AIR DENSITY KG/M**3 3 0 10 + 013240 AIR DENSITY KG/M**3 3 0 10 + 013241 CONVECTIVE AVAILABLE POTENTIAL ENERGY J/KG 1 0 17 014001 LONG-WAVE RADIATION,INTEGRATED OVER 24 HOURS J/M**2 -3 -2048 12 014002 LONG-WAVE RADIATION,INTEGRATED OVER PERIOD SPECIFIED J/M**2 -3 -2048 12 014003 SHORT-WAVE RADIATION,INTEGRATED OVER 24 HOURS J/M**2 -3 -2048 12 diff -Nru wreport-3.6/tables/B000000000981301.txt wreport-3.15/tables/B000000000981301.txt --- wreport-3.6/tables/B000000000981301.txt 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/tables/B000000000981301.txt 2016-09-29 13:37:47.000000000 +0000 @@ -252,7 +252,7 @@ 002197 SATELLITE CHANNEL CENTRE FREQUENCY Hz -8 0 26 002198 SATELLITE CHANNEL BAND WIDTH Hz -8 0 26 002199 INTEGRATED MEAN HUMIDITY COMPUTATIONAL METHOD CODE TABLE 2199 0 0 4 - 002200 LATITUDINAL RESOLUTION DEGREE 5 25 + 002200 LATITUDINAL RESOLUTION DEGREE 5 0 25 002201 SIMULATED SATELLITE INSTRUMENT FLAG TABLE 2201 0 0 4 002202 SIMULATED DATA PROCESSING TECHNIQUE USED FLAG TABLE 2202 0 0 4 002205 LATITUDINAL RESOLUTION DEGREE 3 0 9 diff -Nru wreport-3.6/tables/B000000002551104.txt wreport-3.15/tables/B000000002551104.txt --- wreport-3.6/tables/B000000002551104.txt 2015-08-05 15:39:18.000000000 +0000 +++ wreport-3.15/tables/B000000002551104.txt 2016-09-29 13:37:47.000000000 +0000 @@ -334,7 +334,7 @@ 010009 Geopotential height GPM 0 -1000 17 GPM 0 5 010010 Minimum pressure reduced to mean sea level PA -1 0 14 PA -1 5 010011 Maximum pressure reduced to mean sea level PA -1 0 14 PA -1 5 - 010031 In direction of the North Pole, distance from the Earths centre M 2 -1073741824 31 M 2 10 + 010031 In direction of the North Pole, distance from the Earth's centre M 2 -1073741824 31 M 2 10 010040 Number of retrieved layers NUMERIC 0 0 10 NUMERIC 0 4 010050 Standard deviation altitude M 2 0 16 M 2 5 010061 3-hour pressure change PA -1 -500 10 PA -1 4 @@ -392,29 +392,29 @@ 011077 Reporting interval or averaging time for Eddy Dissipation Rate S 0 0 12 S 0 4 011081 Model wind direction at 10m DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 011082 Model wind speed at 10m M S-1 2 0 14 M S-1 2 4 - 012001 Temperature/dry-bulb temperature K 1 0 12 C 1 3 - 012002 Wet-bulb temperature K 1 0 12 C 1 3 - 012003 Dew-point temperature K 1 0 12 C 1 3 - 012004 Dry-bulb temperature at 2 m K 1 0 12 C 1 3 - 012005 Wet-bulb temperature at 2 m K 1 0 12 C 1 3 - 012006 Dew-point temperature at 2 m K 1 0 12 C 1 3 - 012007 Virtual temperature K 1 0 12 C 1 3 - 012011 Maximum temperature, at height and over period specified K 1 0 12 C 1 3 - 012012 Minimum temperature, at height and over period specified K 1 0 12 C 1 3 - 012013 Ground minimum temperature, past 12 hours K 1 0 12 C 1 3 - 012014 Maximum temperature at 2 m, past 12 hours K 1 0 12 C 1 3 - 012015 Minimum temperature at 2 m, past 12 hours K 1 0 12 C 1 3 - 012016 Maximum temperature at 2 m, past 24 hours K 1 0 12 C 1 3 - 012017 Minimum temperature at 2 m, past 24 hours K 1 0 12 C 1 3 - 012021 Maximum temperature at 2m K 2 0 16 C 2 4 - 012022 Minimum temperature at 2m K 2 0 16 C 2 4 - 012030 Soil temperature K 1 0 12 C 1 3 - 012051 Standard deviation temperature K 1 0 10 C 1 3 - 012052 Highest daily mean temperature K 1 0 12 C 1 3 - 012053 Lowest daily mean temperature K 1 0 12 C 1 3 - 012061 Skin temperature K 1 0 12 C 1 3 - 012062 Equivalent black body temperature K 1 0 12 C 1 3 - 012063 Brightness temperature K 1 0 12 C 1 3 + 012001 Temperature/dry-bulb temperature K 1 0 12 °C 1 3 + 012002 Wet-bulb temperature K 1 0 12 °C 1 3 + 012003 Dew-point temperature K 1 0 12 °C 1 3 + 012004 Dry-bulb temperature at 2 m K 1 0 12 °C 1 3 + 012005 Wet-bulb temperature at 2 m K 1 0 12 °C 1 3 + 012006 Dew-point temperature at 2 m K 1 0 12 °C 1 3 + 012007 Virtual temperature K 1 0 12 °C 1 3 + 012011 Maximum temperature, at height and over period specified K 1 0 12 °C 1 3 + 012012 Minimum temperature, at height and over period specified K 1 0 12 °C 1 3 + 012013 Ground minimum temperature, past 12 hours K 1 0 12 °C 1 3 + 012014 Maximum temperature at 2 m, past 12 hours K 1 0 12 °C 1 3 + 012015 Minimum temperature at 2 m, past 12 hours K 1 0 12 °C 1 3 + 012016 Maximum temperature at 2 m, past 24 hours K 1 0 12 °C 1 3 + 012017 Minimum temperature at 2 m, past 24 hours K 1 0 12 °C 1 3 + 012021 Maximum temperature at 2m K 2 0 16 °C 2 4 + 012022 Minimum temperature at 2m K 2 0 16 °C 2 4 + 012030 Soil temperature K 1 0 12 °C 1 3 + 012051 Standard deviation temperature K 1 0 10 °C 1 3 + 012052 Highest daily mean temperature K 1 0 12 °C 1 3 + 012053 Lowest daily mean temperature K 1 0 12 °C 1 3 + 012061 Skin temperature K 1 0 12 °C 1 3 + 012062 Equivalent black body temperature K 1 0 12 °C 1 3 + 012063 Brightness temperature K 1 0 12 °C 1 3 012064 Instrument temperature K 1 0 12 K 1 4 012065 Standard deviation brightness temperature K 1 0 12 K 1 4 012070 Warm load temperature K 2 0 16 K 2 5 @@ -422,29 +422,29 @@ 012072 Radiance W M-2 SR-1 6 0 31 W M-2SR-1 6 9 012075 Spectral radiance W M-3 SR-1 -3 0 16 W M-3SR-1 -3 5 012076 Radiance W M-2 SR-1 3 0 16 W M-2SR-1 3 5 - 012101 Temperature/dry-bulb temperature K 2 0 16 C 2 4 - 012102 Wet-bulb temperature K 2 0 16 C 2 4 - 012103 Dew-point temperature K 2 0 16 C 2 4 - 012104 Dry-bulb temperature at 2m K 2 0 16 C 2 4 - 012105 Web-bulb temperature at 2m K 2 0 16 C 2 4 - 012106 Dew-point temperature at 2m K 2 0 16 C 2 4 - 012107 Virtual temperature K 2 0 16 C 2 4 - 012111 Maximum temperature, at height and over period specified K 2 0 16 C 2 4 - 012112 Minimum temperature, at height and over period specified K 2 0 16 C 2 4 - 012113 Ground minimum temperature, past 12 hours K 2 0 16 C 2 4 - 012114 Maximum temperature at 2m, past 12 hours K 2 0 16 C 2 4 - 012115 Minimum temperature at 2m, past 12 hours K 2 0 16 C 2 4 - 012116 Maximum temperature at 2m, past 24 hours K 2 0 16 C 2 4 - 012117 Minimum temperature at 2m, past 24 hours K 2 0 16 C 2 4 - 012118 Maximum temperature at height specified, past 24 hours K 2 0 16 C 2 4 - 012119 Minimum temperature at height specified, past 24 hours K 2 0 16 C 2 4 - 012130 Soil temperature K 2 0 16 C 2 4 - 012151 Standard deviation of daily mean temperature K 2 0 12 C 2 4 - 012152 Highest daily mean temperature K 2 0 16 C 2 4 - 012153 Lowest daily mean temperature K 2 0 16 C 2 4 - 012161 Skin temperature K 2 0 16 C 2 4 - 012162 Equivalent black body temperature K 2 0 16 C 2 4 - 012163 Brightness temperature K 2 0 16 C 2 4 + 012101 Temperature/dry-bulb temperature K 2 0 16 °C 2 4 + 012102 Wet-bulb temperature K 2 0 16 °C 2 4 + 012103 Dew-point temperature K 2 0 16 °C 2 4 + 012104 Dry-bulb temperature at 2m K 2 0 16 °C 2 4 + 012105 Web-bulb temperature at 2m K 2 0 16 °C 2 4 + 012106 Dew-point temperature at 2m K 2 0 16 °C 2 4 + 012107 Virtual temperature K 2 0 16 °C 2 4 + 012111 Maximum temperature, at height and over period specified K 2 0 16 °C 2 4 + 012112 Minimum temperature, at height and over period specified K 2 0 16 °C 2 4 + 012113 Ground minimum temperature, past 12 hours K 2 0 16 °C 2 4 + 012114 Maximum temperature at 2m, past 12 hours K 2 0 16 °C 2 4 + 012115 Minimum temperature at 2m, past 12 hours K 2 0 16 °C 2 4 + 012116 Maximum temperature at 2m, past 24 hours K 2 0 16 °C 2 4 + 012117 Minimum temperature at 2m, past 24 hours K 2 0 16 °C 2 4 + 012118 Maximum temperature at height specified, past 24 hours K 2 0 16 °C 2 4 + 012119 Minimum temperature at height specified, past 24 hours K 2 0 16 °C 2 4 + 012130 Soil temperature K 2 0 16 °C 2 4 + 012151 Standard deviation of daily mean temperature K 2 0 12 °C 2 4 + 012152 Highest daily mean temperature K 2 0 16 °C 2 4 + 012153 Lowest daily mean temperature K 2 0 16 °C 2 4 + 012161 Skin temperature K 2 0 16 °C 2 4 + 012162 Equivalent black body temperature K 2 0 16 °C 2 4 + 012163 Brightness temperature K 2 0 16 °C 2 4 012164 Instrument temperature K 2 0 16 K 2 5 012171 Coldest cluster temperature K 2 0 16 K 2 5 015001 Total ozone DU 0 0 10 DU 0 4 @@ -769,12 +769,12 @@ 027004 Alternate latitude (high accuracy) DEGREE 5 -9000000 25 DEGREE 5 7 027020 Satellite location counter NUMERIC 0 0 16 NUMERIC 0 5 027021 Satellite sublocation dimension NUMERIC 0 0 16 NUMERIC 0 5 - 027031 In direction of 0 degrees longitude, distance from the Earths c M 2 -1073741824 31 M 2 10 + 027031 In direction of 0 degrees longitude, distance from the Earth’s c M 2 -1073741824 31 M 2 10 028001 Longitude (high accuracy) DEGREE 5 -18000000 26 DEGREE 5 8 028002 Longitude (coarse accuracy) DEGREE 2 -18000 16 DEGREE 2 5 028003 Alternate longitude (coarse accuracy) DEGREE 2 -18000 16 DEGREE 2 5 028004 Alternate longitude (high accuracy) DEGREE 5 -18000000 26 DEGREE 5 8 - 028031 In direction 90 degrees East, distance from the Earths centre M 2 -1073741824 31 M 2 10 + 028031 In direction 90 degrees East, distance from the Earth’s centre M 2 -1073741824 31 M 2 10 029001 Projection type CODE TABLE 0 0 3 CODE TABLE 0 1 029002 Co-ordinate grid type CODE TABLE 0 0 3 CODE TABLE 0 1 029193 Long Origin DEGREE 2 -18000 16 DEGREE 2 5 diff -Nru wreport-3.6/tables/check_btable wreport-3.15/tables/check_btable --- wreport-3.6/tables/check_btable 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/tables/check_btable 2016-09-29 13:37:47.000000000 +0000 @@ -0,0 +1,52 @@ +#!/usr/bin/python3 + +import sys + +def parse_line(line): + if len(line) < 118: + raise ValueError("bufr table line too short") + return "0" + line[2:7] + + +def check_file(fname): + is_ok = True + + last_bcode = 0 + with open(fname, "rb") as fd: + for idx, line in enumerate(fd, start=1): + try: + line = line.decode("utf-8").rstrip() + except UnicodeDecodeError as e: + print("{}:{}:encoding error: {}".format(fname, idx, str(e)), file=sys.stderr) + is_ok = False + continue + + try: + bcode = parse_line(line) + int_bcode = int(bcode) + except ValueError as e: + print("{}:{}:{}".format(fname, idx, str(e)), file=sys.stderr) + is_ok = False + continue + + if int_bcode <= last_bcode: + print("{}:{}:B code {} is not greater than the B code in the previous line".format(fname, idx, bcode), file=sys.stderr) + is_ok = False + continue + else: + last_bcode = int_bcode + + return is_ok + + +def main(): + import argparse + parser = argparse.ArgumentParser(description="Validate BUFR table files") + parser.add_argument('files', nargs='+', help='input file(s) to validate') + args = parser.parse_args() + all_ok = all([check_file(x) for x in args.files]) + sys.exit(0 if all_ok else 1) + + +if __name__ == "__main__": + main() diff -Nru wreport-3.6/tables/Makefile.am wreport-3.15/tables/Makefile.am --- wreport-3.6/tables/Makefile.am 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/tables/Makefile.am 2016-11-07 10:08:48.000000000 +0000 @@ -73,6 +73,11 @@ D0000000000085014000.txt: D0000000000085014001.txt cp $< $@ -CLEANFILES = $(generated_tables) +tables_ok: check_btable $(bufrbtables) + $(srcdir)/check_btable $(bufrbtables) -EXTRA_DIST = $(crexbtables) $(crexdtables) $(bufrbtables) $(bufrdtables) test.txt +noinst_DATA = tables_ok + +CLEANFILES = $(generated_tables) tables_ok + +EXTRA_DIST = $(crexbtables) $(crexdtables) $(bufrbtables) $(bufrdtables) check_btable test.txt README.md diff -Nru wreport-3.6/tables/Makefile.in wreport-3.15/tables/Makefile.in --- wreport-3.6/tables/Makefile.in 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/tables/Makefile.in 2018-09-19 13:16:11.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -151,7 +151,7 @@ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(tabledir)" -DATA = $(table_DATA) +DATA = $(noinst_DATA) $(table_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -175,7 +175,6 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DEP_LIBS = @DEP_LIBS@ DLLTOOL = @DLLTOOL@ DOXYGEN_WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@ DSYMUTIL = @DSYMUTIL@ @@ -222,6 +221,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_LIBS = @PKGCONFIG_LIBS@ +PKGCONFIG_REQUIRES = @PKGCONFIG_REQUIRES@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ @@ -365,8 +366,9 @@ B0000000000085014000.txt D0000000000085014000.txt table_DATA = $(crexbtables) $(crexdtables) $(bufrbtables) $(bufrdtables) $(generated_tables) -CLEANFILES = $(generated_tables) -EXTRA_DIST = $(crexbtables) $(crexdtables) $(bufrbtables) $(bufrdtables) test.txt +noinst_DATA = tables_ok +CLEANFILES = $(generated_tables) tables_ok +EXTRA_DIST = $(crexbtables) $(crexdtables) $(bufrbtables) $(bufrdtables) check_btable test.txt README.md all: all-am .SUFFIXES: @@ -387,8 +389,8 @@ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -433,7 +435,10 @@ cscope cscopelist: -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -589,6 +594,9 @@ D0000000000085014000.txt: D0000000000085014001.txt cp $< $@ +tables_ok: check_btable $(bufrbtables) + $(srcdir)/check_btable $(bufrbtables) + # 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: diff -Nru wreport-3.6/tables/README.md wreport-3.15/tables/README.md --- wreport-3.6/tables/README.md 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/tables/README.md 2016-11-07 10:08:48.000000000 +0000 @@ -0,0 +1,75 @@ +# Format of table files + +Table files follow the format of the tables used by the [ECMWF bufrdc +library](https://software.ecmwf.int/wiki/display/BUFR/BUFRDC+Home). + +Each table has columns of a fixed size, and there are no column headers. + +## B table files + +Column 0: 1 space. + +Column 1: 6 characters, B table code. + +Column 7: 1 space. + +Column 8: 64 characters, description. + +Column 72: 1 space. + +Column 73: 24 characters, BUFR unit. + +Column 97: 1 space. + +Column 98: 3 characters, BUFR decimal scale. + +Column 101: 1 space. + +Column 102: 12 characters, binary reference value. + +Column 114: 1 space. + +Column 115: 3 characters, binary bit length. + +Column 118: 1 space. + +Column 119: 24 characters, CREX unit. + +Column 143: 1 space. + +Column 144: 2 characters: CREX decimal scale. + +Column 146: 1 space. + +Column 147: 9 characters: CREX character length. + +## D table files + +### First row in a sequence: + +Column 0: 1 space. + +Column 1: 6 characters, D table code. + +Column 7: 1 space. + +Column 8: 2 characters, length of code sequence. + +Column 10: 1 space. + +Column 11: first B or D table code in the sequence. + +### Following rows in a sequence: + +Column 0: 1 space. + +Column 1: 6 spaces. + +Column 7: 1 space. + +Column 8: 2 spaces. + +Column 10: 1 space. + +Column 11: B or D table code in the sequence. + Binary files /tmp/tmpQffHEU/ARzBTavm6x/wreport-3.6/testdata/bufr/afl-src01flip1-pos10.bufr and /tmp/tmpQffHEU/c4GyE17mSb/wreport-3.15/testdata/bufr/afl-src01flip1-pos10.bufr differ Binary files /tmp/tmpQffHEU/ARzBTavm6x/wreport-3.6/testdata/bufr/afl-src4824splice-rep8.bufr and /tmp/tmpQffHEU/c4GyE17mSb/wreport-3.15/testdata/bufr/afl-src4824splice-rep8.bufr differ Binary files /tmp/tmpQffHEU/ARzBTavm6x/wreport-3.6/testdata/bufr/issue16.bufr and /tmp/tmpQffHEU/c4GyE17mSb/wreport-3.15/testdata/bufr/issue16.bufr differ Binary files /tmp/tmpQffHEU/ARzBTavm6x/wreport-3.6/testdata/bufr/issue16-onenull.bufr and /tmp/tmpQffHEU/c4GyE17mSb/wreport-3.15/testdata/bufr/issue16-onenull.bufr differ Binary files /tmp/tmpQffHEU/ARzBTavm6x/wreport-3.6/testdata/bufr/issue16-twonull.bufr and /tmp/tmpQffHEU/c4GyE17mSb/wreport-3.15/testdata/bufr/issue16-twonull.bufr differ diff -Nru wreport-3.6/testdata/bufr/short0.bufr wreport-3.15/testdata/bufr/short0.bufr --- wreport-3.6/testdata/bufr/short0.bufr 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/testdata/bufr/short0.bufr 2018-07-26 09:09:50.000000000 +0000 @@ -0,0 +1 @@ +B \ No newline at end of file diff -Nru wreport-3.6/testdata/bufr/short1.bufr wreport-3.15/testdata/bufr/short1.bufr --- wreport-3.6/testdata/bufr/short1.bufr 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/testdata/bufr/short1.bufr 2018-07-26 09:10:14.000000000 +0000 @@ -0,0 +1 @@ +BUFR \ No newline at end of file diff -Nru wreport-3.6/testdata/bufr/short2.bufr wreport-3.15/testdata/bufr/short2.bufr --- wreport-3.6/testdata/bufr/short2.bufr 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/testdata/bufr/short2.bufr 2018-07-26 09:12:55.000000000 +0000 @@ -0,0 +1 @@ +BUFR7777 \ No newline at end of file Binary files /tmp/tmpQffHEU/ARzBTavm6x/wreport-3.6/testdata/bufr/short3.bufr and /tmp/tmpQffHEU/c4GyE17mSb/wreport-3.15/testdata/bufr/short3.bufr differ diff -Nru wreport-3.6/testdata/Makefile.in wreport-3.15/testdata/Makefile.in --- wreport-3.6/testdata/Makefile.in 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/testdata/Makefile.in 2018-09-19 13:16:11.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -145,7 +145,6 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DEP_LIBS = @DEP_LIBS@ DLLTOOL = @DLLTOOL@ DOXYGEN_WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@ DSYMUTIL = @DSYMUTIL@ @@ -192,6 +191,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_LIBS = @PKGCONFIG_LIBS@ +PKGCONFIG_REQUIRES = @PKGCONFIG_REQUIRES@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ @@ -294,8 +295,8 @@ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -319,7 +320,10 @@ cscope cscopelist: -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ diff -Nru wreport-3.6/testenv wreport-3.15/testenv --- wreport-3.6/testenv 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/testenv 2018-05-14 15:34:17.000000000 +0000 @@ -31,26 +31,23 @@ fi if [ ! -z "$DEBUGGER" ] then - if [ -x $DIR/.libs/lt-$BASE ] + echo "Running $DEBUGGER $CMD $ARGS" + if libtool --mode=execute $DEBUGGER $CMD $ARGS then - CMD="$DIR/.libs/lt-$BASE" - fi - - echo "Running $DEBUGGER $CMD $ARGS" RES=0 - if ! $DEBUGGER $CMD $ARGS - then - RES=$? - echo "Failed with result $RES" - fi + else + RES=$? + echo "Failed with result $RES" + fi else - echo "Running $CMD $ARGS" + echo "Running $CMD $ARGS" + if $CMD $ARGS + then RES=0 - if ! $CMD $ARGS - then - RES=$? - echo "Failed with result $RES" - fi + else + RES=$? + echo "Failed with result $RES" + fi fi diff -Nru wreport-3.6/.travis-build.sh wreport-3.15/.travis-build.sh --- wreport-3.6/.travis-build.sh 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/.travis-build.sh 2018-01-27 16:06:58.000000000 +0000 @@ -0,0 +1,40 @@ +#!/bin/bash +set -ex + +image=$1 + +if [[ $image =~ ^centos: ]] +then + pkgcmd="yum" + builddep="yum-builddep" + sed -i '/^tsflags=/d' /etc/yum.conf + yum install -y epel-release + yum install -y @buildsys-build + yum install -y yum-utils + yum install -y git +elif [[ $image =~ ^fedora: ]] +then + pkgcmd="dnf" + builddep="dnf builddep" + sed -i '/^tsflags=/d' /etc/dnf/dnf.conf + dnf install -y @buildsys-build + dnf install -y 'dnf-command(builddep)' + dnf install -y git +fi + +$builddep -y fedora/SPECS/wreport.spec + +if [[ $image =~ ^fedora: || $image =~ ^centos: ]] +then + pkgname=wreport-$(git describe --abbrev=0 --tags --match='v*' | sed -e 's,^v,,g') + mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} + cp fedora/SPECS/wreport.spec ~/rpmbuild/SPECS/wreport.spec + git archive --prefix=$pkgname/ --format=tar HEAD | gzip -c > ~/rpmbuild/SOURCES/$pkgname.tar.gz + rpmbuild -ba ~/rpmbuild/SPECS/wreport.spec + find ~/rpmbuild/{RPMS,SRPMS}/ -name "${pkgname}*rpm" -exec cp -v {} . \; + # TODO upload ${pkgname}*.rpm to github release on deploy stage +else + autoreconf -ifv + ./configure + make check +fi diff -Nru wreport-3.6/.travis.yml wreport-3.15/.travis.yml --- wreport-3.6/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/.travis.yml 2018-05-12 13:35:30.000000000 +0000 @@ -0,0 +1,27 @@ +language: generic + +sudo: required + +services: + - docker + +script: + - docker run -v ${TRAVIS_BUILD_DIR}:/root/src/ -w /root/src/ $DOCKER_IMAGE /bin/bash .travis-build.sh $DOCKER_IMAGE + +env: + - DOCKER_IMAGE=centos:7 + - DOCKER_IMAGE=fedora:28 + - DOCKER_IMAGE=fedora:27 + - DOCKER_IMAGE=fedora:26 + +before_deploy: + - openssl aes-256-cbc -K $encrypted_9241d2ed5547_key -iv $encrypted_9241d2ed5547_iv -in .copr.enc -out .copr -d + +deploy: + skip_cleanup: true + provider: script + script: docker run -v ${TRAVIS_BUILD_DIR}:/root/src/ -w /root/src/ fedora:latest /bin/sh -c "dnf install -y copr-cli && copr-cli --config .copr build --nowait simc/stable fedora/SPECS/wreport.spec" + + on: + branch: master + condition: $DOCKER_IMAGE = centos:7 diff -Nru wreport-3.6/wreport/buffers/bufr.cc wreport-3.15/wreport/buffers/bufr.cc --- wreport-3.6/wreport/buffers/bufr.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/buffers/bufr.cc 2018-05-14 15:34:17.000000000 +0000 @@ -37,538 +37,6 @@ namespace wreport { namespace buffers { -BufrInput::BufrInput(const std::string& in) -{ - data = (const unsigned char*)in.data(); - data_len = in.size(); - for (unsigned i = 0; i < sizeof(sec)/sizeof(sec[0]); ++i) - sec[i] = 0; -} - -void BufrInput::scan_section_length(unsigned sec_no) -{ - if (sec[sec_no] + 3 > data_len) - parse_error(sec[sec_no], "section %d (%s) is too short to hold the section size indicator", - sec_no, bufr_sec_names[sec_no]); - - sec[sec_no + 1] = sec[sec_no] + read_number(sec_no, 0, 3); - - if (sec[sec_no + 1] > data_len) - parse_error(sec[sec_no], "section %d (%s) claims to end past the end of the BUFR message", - sec_no, bufr_sec_names[sec_no]); -} - -void BufrInput::scan_lead_sections() -{ - check_available_data(sec[0], 8, "section 0 of BUFR message (indicator section)"); - sec[1] = sec[0] + 8; - scan_section_length(1); -} - -void BufrInput::scan_other_sections(bool has_optional) -{ - if (has_optional) - { - scan_section_length(2); - } else - sec[3] = sec[2]; - - for (unsigned i = 3; i < 5; ++i) - scan_section_length(i); - - s4_cursor = sec[4] + 4; -} - -void BufrInput::debug_dump_next_bits(const char* desc, int count) const -{ - fputs(desc, stderr); - size_t cursor = s4_cursor; - int pbyte = this->pbyte; - int pbyte_len = this->pbyte_len; - int i; - - for (i = 0; i < count; ++i) - { - if (cursor == data_len) - break; - if (pbyte_len == 0) - { - pbyte_len = 8; - pbyte = data[cursor++]; - putc(' ', stderr); - } - putc((pbyte & 0x80) ? '1' : '0', stderr); - pbyte <<= 1; - --pbyte_len; - } - putc('\n', stderr); -} - -void BufrInput::parse_error(const char* fmt, ...) const -{ - char* context; - char* message; - - va_list ap; - va_start(ap, fmt); - if (vasprintf(&message, fmt, ap) == -1) - message = nullptr; - va_end(ap); - - if (asprintf(&context, "%s:%zd+%u: %s", fname, start_offset, s4_cursor, message ? message : fmt) == -1) - context = nullptr; - free(message); - - string msg(context ? context : fmt); - free(context); - - throw error_parse(msg); -} - -void BufrInput::parse_error(unsigned pos, const char* fmt, ...) const -{ - char* context; - char* message; - - va_list ap; - va_start(ap, fmt); - if (vasprintf(&message, fmt, ap) == -1) - message = nullptr; - va_end(ap); - - if (asprintf(&context, "%s:%zd+%u: %s", fname, start_offset, pos, message ? message : fmt) == -1) - context = nullptr; - free(message); - - string msg(context ? context : fmt); - free(context); - throw error_parse(msg); -} - -void BufrInput::parse_error(unsigned section, unsigned pos, const char* fmt, ...) const -{ - char* context; - char* message; - - va_list ap; - va_start(ap, fmt); - if (vasprintf(&message, fmt, ap) == -1) - message = nullptr; - va_end(ap); - - if (asprintf(&context, "%s:%zd+%u: %s (%db inside section %s)", - fname, start_offset, sec[section] + pos, message ? message : fmt, - pos, bufr_sec_names[section]) == -1) - context = nullptr; - free(message); - - string msg(context ? context : fmt); - free(context); - throw error_parse(msg); -} - -void BufrInput::check_available_data(unsigned pos, size_t datalen, const char* expected) -{ - if (pos + datalen > data_len) - parse_error(pos, "end of BUFR message while looking for %s", expected); -} - -void BufrInput::check_available_data(unsigned section, unsigned pos, size_t datalen, const char* expected) -{ - // TODO: check that sec[section] + pos + datalen > sec[section + 1] instead? - // TODO: in that case, make a fake section 6 which starts at the end of - // TODO: BUFR data - if (sec[section] + pos + datalen > data_len) - parse_error(section, pos, "end of BUFR message while looking for %s", expected); -} - -bool BufrInput::decode_string(unsigned bit_len, char* str, size_t& len) -{ - int toread = bit_len; - bool missing = true; - len = 0; - - while (toread > 0) - { - int count = toread > 8 ? 8 : toread; - uint32_t bitval = get_bits(count); - /* Check that the string is not all 0xff, meaning missing value */ - if (bitval != 0xff && bitval != 0) - missing = false; - str[len++] = bitval; - toread -= count; - } - - if (!missing) - { - str[len] = 0; - - /* Convert space-padding into zero-padding */ - for (; len > 1 && (str[len - 1] == 0 || isspace(str[len - 1])); - --len) - str[len - 1] = 0; - } - - return !missing; -} - -void BufrInput::decode_string(Var& dest) -{ - Varinfo info = dest.info(); - - char str[info->bit_len / 8 + 2]; - size_t len; - bool missing = !decode_string(info->bit_len, str, len); - - /* Store the variable that we found */ - // Set the variable value - if (!missing) - dest.setc(str); -} - -void BufrInput::decode_binary(Var& dest) -{ - Varinfo info = dest.info(); - - unsigned char buf[info->bit_len / 8 + 1]; - size_t len = 0; - unsigned toread = info->bit_len; - bool missing = true; - - while (toread > 0) - { - unsigned count = toread > 8 ? 8 : toread; - uint32_t bitval = get_bits(count); - /* Check that the string is not all 0xff, meaning missing value */ - if (bitval != 0xff) - missing = false; - buf[len++] = bitval; - toread -= count; - } - - /* Store the variable that we found */ - // Set the variable value - if (!missing) - dest.setc((char*)buf); -} - -void BufrInput::decode_number(Var& dest) -{ - Varinfo info = dest.info(); - - uint32_t val = get_bits(info->bit_len); - - // TRACE("datasec:decode_b_num:reading %s (%s), size %d, scale %d, starting point %d\n", info->desc, info->bufr_unit, info->bit_len, info->scale, val); - - // Check if there are bits which are not 1 (that is, if the value is present) - // In case of delayed replications, there is no missing value - bool missing = false; - if (WR_VAR_X(info->code) == 31 && WR_VAR_F(info->code) == 0) - switch (WR_VAR_Y(info->code)) - { - case 0: - case 1: - case 2: - case 11: - case 12: - break; - default: - missing = (val == all_ones(info->bit_len)); - } - else - missing = (val == all_ones(info->bit_len)); - - // TRACE("datasec:decode_b_num:len %d val %d info-len %d info-desc %s\n", info->bit_len, val, info->bit_len, info->desc); - - /* Store the variable that we found */ - if (missing) - { - /* Create the new Var */ - // TRACE("datasec:decode_b_num:decoded as missing\n"); - dest.unset(); - } else { - double dval = info->decode_binary(val); - // TRACE("datasec:decode_b_num:decoded as %f %s\n", dval, info->bufr_unit); - /* Create the new Var */ - dest.setd(dval); - } -} - -bool BufrInput::decode_compressed_base(Varinfo info, uint32_t& base, uint32_t& diffbits) -{ - // Data field base value - base = get_bits(info->bit_len); - - // Check if there are bits which are not 1 (that is, if the value is present) - bool missing = (base == all_ones(info->bit_len)); - - // We just decoded the base value. Now we need to decode all the offsets - - // Decode the number of bits (encoded in 6 bits) that these difference - // values occupy - diffbits = get_bits(6); - if (missing && diffbits != 0) - error_consistency::throwf("When decoding compressed BUFR data, the difference bit length must be 0 (and not %d like in this case) when the base value is missing", diffbits); - - return missing; -} - -void BufrInput::decode_compressed_number(Var& dest, uint32_t base, unsigned diffbits) -{ - Varinfo info = dest.info(); - - // Decode the difference value - uint32_t diff = get_bits(diffbits); - - // Check if it's all 1s: in that case it's a missing value - if (base == all_ones(info->bit_len) || diff == all_ones(diffbits)) - { - /* Missing value */ - //TRACE("datasec:decode_b_num:decoded[%d] as missing\n", i); - dest.unset(); - } else { - // Compute the value for this subset - uint32_t newval = base + diff; - double dval = info->decode_binary(newval); - TRACE("BufrInput:decode_number:decoded diffbits %u %u+%u=%u->%f %s\n", - diffbits, base, diff, newval, dval, info->bufr_unit); - - /* Create the new Var */ - dest.setd(dval); - } -} - -//void BufrInput::decode_compressed_number(Varinfo info, unsigned subsets, const bulletin::AssociatedField& associated_field, std::function dest) -void BufrInput::decode_compressed_number(Varinfo info, unsigned associated_field_bits, unsigned subsets, std::function dest) -{ - Var var(info); - - // debug_dump_next_bits("DECODE NUMBER: ", 30); - - /* I could not find any specification describing the behaviour of associated fields in compressed BUFRs. - * - * By empirical observation, I assume this behaviour: - * - * - $ASSOCIATED_FIELD_BITS bits of base value for the associated field - * - 6 bits specifying the number of bits used to encode the associated - * field difference values - * - base value for the actual variable (number of bits defined in table B) - * - 6 difference bits for the actual variable - * - * Then, for each subset: - * - the difference bits for the associated field - * - the difference bits for the actual variable - */ - - /// Associated field base value - uint32_t af_base = get_bits(associated_field_bits); - /// Number of bits used to encode the associated field differences - uint32_t af_diffbits = get_bits(6); - - // Data field base value - uint32_t base = get_bits(info->bit_len); - - //TRACE("datasec:decode_b_num:reading %s (%s), size %d, scale %d, starting point %d\n", info->desc, info->bufr_unit, info->bit_len, info->scale, base); - - /* Check if there are bits which are not 1 (that is, if the value is present) */ - bool missing = (base == all_ones(info->bit_len)); - - /*bufr_decoder_debug(decoder, " %s: %d%s\n", info.desc, base, info.type);*/ - //TRACE("datasec:decode_b_num:len %d base %d info-len %d info-desc %s\n", info->bit_len, base, info->bit_len, info->desc); - - /* Store the variable that we found */ - - /* If compression is in use, then we just decoded the base value. Now - * we need to decode all the offsets */ - - /* Decode the number of bits (encoded in 6 bits) that these difference - * values occupy */ - uint32_t diffbits = get_bits(6); - if (missing && diffbits != 0) - error_consistency::throwf("When decoding compressed BUFR data, the difference bit length must be 0 (and not %d like in this case) when the base value is missing", diffbits); - - //TRACE("Compressed number, base value %d diff bits %d\n", base, diffbits); - - for (unsigned i = 0; i < subsets; ++i) - { - uint32_t af_value = af_base + get_bits(af_diffbits); - decode_compressed_number(var, base, diffbits); - dest(i, move(var), af_value); - } -} - -void BufrInput::decode_compressed_semantic_number(Var& dest, unsigned subsets) -{ - Varinfo info = dest.info(); - - uint32_t base = get_bits(info->bit_len); - - //TRACE("datasec:decode_b_num:reading %s (%s), size %d, scale %d, starting point %d\n", info->desc, info->bufr_unit, info->bit_len, info->scale, base); - - // Check if there are bits which are not 1 (that is, if the value is present) - bool missing = (base == all_ones(info->bit_len)); - - //TRACE("datasec:decode_b_num:len %d base %d info-len %d info-desc %s\n", info->bit_len, base, info->bit_len, info->desc); - - // Store the variable that we found - - /* If compression is in use, then we just decoded the base value. Now we - * need to decode all the offsets. However, since this value cannot change - * across subsets without breaking the alignment of the variables in the - * various subsets, we only need to check that the 6-bits difference value - * size is 0, and use the base value we just decoded as the final value */ - uint32_t diffbits = get_bits(6); - if (diffbits) - error_consistency::throwf("cannot handle a semantic variable (like a repetition count) that differs across subsets"); - - //TRACE("Compressed number, base value %d diff bits %d\n", base, diffbits); - - // Decode the destination variable - if (missing) - { - //TRACE("datasec:decode_b_num:decoded[%d] as missing\n", i); - dest.unset(); - } else { - double dval = info->decode_binary(base); - dest.setd(dval); - } -} - -void BufrInput::decode_string(Varinfo info, unsigned subsets, std::function dest) -{ - char str[info->bit_len / 8 + 2]; - size_t len; - bool missing = !decode_string(info->bit_len, str, len); - - /* Store the variable that we found */ - - /* If compression is in use, then we just decoded the base value. Now - * we need to decode all the offsets */ - - /* Decode the number of bits (encoded in 6 bits) that these difference - * values occupy */ - uint32_t diffbits = get_bits(6); - - //TRACE("datadesc:decode_b_string:compressed string, base:%.*s, diff bits %d\n", (int)len, str, diffbits); - - if (diffbits != 0) - { - Var var(info); - - /* For compressed strings, the reference value must be all zeros */ - for (size_t i = 0; i < len; ++i) - if (str[i] != 0) - error_unimplemented::throwf("compressed strings with %d bit deltas have non-zero reference value", diffbits); - - /* Let's also check that the number of - * difference characters is the same length as - * the reference string */ - if (diffbits > len) - error_unimplemented::throwf("compressed strings with %zd characters have %d bit deltas (deltas should not be longer than field)", len, diffbits); - - for (unsigned i = 0; i < subsets; ++i) - { - // Set the variable value - if (decode_string(diffbits * 8, str, len)) - { - /* Compute the value for this subset */ - //TRACE("datadesc:decode_b_string:decoded[%d] as \"%s\"\n", i, str); - var.setc(str); - } else { - /* Missing value */ - //TRACE("datadesc:decode_b_string:decoded[%d] as missing\n", i); - var.unset(); - } - - // Add it to this subset - dest(i, move(var)); - } - } else { - Var var(info); - if (!missing) var.setc(str); - - // Add the string to all the subsets - for (unsigned i = 0; i < subsets; ++i) - dest(i, Var(var)); - } -} - -void BufrInput::decode_string(Var& dest, unsigned subsets) -{ - Varinfo info = dest.info(); - - char str[info->bit_len / 8 + 2]; - size_t len; - bool missing = !decode_string(info->bit_len, str, len); - - /* Store the variable that we found */ - - /* If compression is in use, then we just decoded the base value. Now - * we need to decode all the offsets */ - - /* Decode the number of bits (encoded in 6 bits) that these difference - * values occupy */ - uint32_t diffbits = get_bits(6); - - //TRACE("datadesc:decode_b_string:compressed string, base:%.*s, diff bits %d\n", (int)len, str, diffbits); - - if (diffbits == 0) - { - if (!missing) - dest.setc(str); - } else { - /* For compressed strings, the reference value must be all zeros */ - for (size_t i = 0; i < len; ++i) - if (str[i] != 0) - error_unimplemented::throwf("compressed strings with %d bit deltas have non-zero reference value", diffbits); - - /* Let's also check that the number of - * difference characters is the same length as - * the reference string */ - if (diffbits > len) - error_unimplemented::throwf("compressed strings with %zd characters have %d bit deltas (deltas should not be longer than field)", len, diffbits); - - // Set the variable value - if (decode_string(diffbits * 8, str, len)) - { - /* Compute the value for this subset */ - //TRACE("datadesc:decode_b_string:decoded[%d] as \"%s\"\n", i, str); - dest.setc(str); - } else { - /* Missing value */ - //TRACE("datadesc:decode_b_string:decoded[%d] as missing\n", i); - dest.unset(); - } - - Var copy(dest.info()); - for (unsigned i = 1; i < subsets; ++i) - { - // TODO: only compare the diffbits without needing to reconstruct the var - - // Set the variable value - if (decode_string(diffbits * 8, str, len)) - { - /* Compute the value for this subset */ - //TRACE("datadesc:decode_b_string:decoded[%d] as \"%s\"\n", i, str); - copy.setc(str); - } else { - /* Missing value */ - //TRACE("datadesc:decode_b_string:decoded[%d] as missing\n", i); - copy.unset(); - } - - if (dest != copy) - { - string val1 = dest.format(); - string val2 = copy.format(); - error_consistency::throwf("When decoding %d%02d%03d from compressed BUFR data, decoded values differ (%s != %s) but should all be the same", - WR_VAR_F(dest.code()), WR_VAR_X(dest.code()), WR_VAR_Y(dest.code()), - val2.c_str(), val1.c_str()); - } - } - } -} - BufrOutput::BufrOutput(std::string& out) : out(out), pbyte(0), pbyte_len(0) diff -Nru wreport-3.6/wreport/buffers/bufr.h wreport-3.15/wreport/buffers/bufr.h --- wreport-3.6/wreport/buffers/bufr.h 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/buffers/bufr.h 2018-05-14 15:34:17.000000000 +0000 @@ -13,466 +13,6 @@ namespace buffers { /** - * Binary buffer with bit-level read operations - */ -class BufrInput -{ -protected: - /** - * Scan length of section \a sec_no, filling in the start of the next - * section in sec[sec_no + 1] - */ - void scan_section_length(unsigned sec_no); - -public: - /// Input buffer - const uint8_t* data; - - /// Input buffer size - size_t data_len; - - /** - * Input file name (optional). - * - * If available, it will be used to generate better error messages. - * - * If not available, it is NULL. - */ - const char* fname = nullptr; - - /** - * File offset of the start of the message. - * - * If available, it will be used to generate better error messages. - * - * If not available, it is 0. - */ - size_t start_offset = 0; - - /// Offset of the byte we are currently decoding - unsigned s4_cursor = 0; - - /// Byte we are currently decoding - uint8_t pbyte = 0; - - /// Bits left in pbyte to decode - int pbyte_len = 0; - - /// Offsets of the start of BUFR sections - unsigned sec[6]; - - - /** - * Wrap a string iinto a BufrInput - * - * @param in - * String with the data to read - */ - BufrInput(const std::string& in); - - /** - * Scan the message filling in the sec[] array of start offsets of sections - * 0 and 1. - * - * We cannot scan past section 1 until we decode it, because we need to - * know if section 2 is present or not - */ - void scan_lead_sections(); - - /** - * Scan the message filling in the sec[] array of section start offsets of - * all sections from 2 on. - * - * It also initialises points s4_cursor to the begin of the data in section - * 4. - * - * @param has_optional - * True if the optional section is present, false if it should be - * skipped. - */ - void scan_other_sections(bool has_optional); - - /// Return the current decoding byte offset - unsigned offset() const { return s4_cursor; } - - /// Return the number of bits left in the message to be decoded - unsigned bits_left() const { return (data_len - s4_cursor) * 8 + pbyte_len; } - - /// Read a byte value at offset \a pos - inline unsigned read_byte(unsigned pos) const - { - return (unsigned)data[pos]; - } - - /// Read a byte value at offset \a pos inside section \a section - inline unsigned read_byte(unsigned section, unsigned pos) const - { - return (unsigned)data[sec[section] + pos]; - } - - /// Read a big endian integer value \a byte_len bytes long, at offset \a pos - unsigned read_number(unsigned pos, unsigned byte_len) const - { - unsigned res = 0; - for (unsigned i = 0; i < byte_len; ++i) - { - res <<= 8; - res |= data[pos + i]; - } - return res; - } - - /** - * Read a big endian integer value \a byte_len bytes long, at offset \a pos - * inside section \a section - */ - inline unsigned read_number(unsigned section, unsigned pos, unsigned byte_len) const - { - return read_number(sec[section] + pos, byte_len); - } - - /** - * Get the integer value of the next 'n' bits from the decode input - * n must be <= 32. - */ - uint32_t get_bits(unsigned n) - { - uint32_t result = 0; - - if (s4_cursor == data_len) - parse_error("end of buffer while looking for %d bits of bit-packed data", n); - - // TODO: review and benchmark and possibly simplify - // (a possible alternative approach is to keep a current bitmask that - // starts at 0x80 and is shifted right by 1 at each read until it - // reaches 0, and get rid of pbyte_len) - for (unsigned i = 0; i < n; i++) - { - if (pbyte_len == 0) - { - pbyte_len = 8; - pbyte = data[s4_cursor++]; - } - result <<= 1; - if (pbyte & 0x80) - result |= 1; - pbyte <<= 1; - pbyte_len--; - } - - return result; - } - - /// Dump to stderr 'count' bits of 'buf', starting at the 'ofs-th' bit - void debug_dump_next_bits(const char* desc, int count) const; - - /// Throw an error_parse at the current decoding location - void parse_error(const char* fmt, ...) const WREPORT_THROWF_ATTRS(2, 3); - - /// Throw an error_parse at the given decoding location - void parse_error(unsigned pos, const char* fmt, ...) const WREPORT_THROWF_ATTRS(3, 4); - - /// Throw an error_parse at the given decoding location inside the given section - void parse_error(unsigned section, unsigned pos, const char* fmt, ...) const WREPORT_THROWF_ATTRS(4, 5); - - /** - * Check that the input buffer contains at least \a datalen characters - * after offset \a pos; throw error_parse otherwise. - * - * @param pos - * Starting offset of the required data - * @param datalen - * Required amount of data expected starting from \a pos - * @param expected - * name of what we are about to decode, used for generating nice error - * messages - */ - void check_available_data(unsigned pos, size_t datalen, const char* expected); - - /** - * Check that the input buffer contains at least \a datalen characters - * after offset \a pos in section \a section; throw error_parse otherwise. - * - * @param section - * Number of the section to check - * @param pos - * Starting offset inside the section of the required data - * @param datalen - * Required amount of data expected starting from \a pos - * @param expected - * Name of what we are about to decode, used for generating nice error - * messages - */ - void check_available_data(unsigned section, unsigned pos, size_t datalen, const char* expected); - - /** - * Decode a compressed number as described by dest.info(), ad set it as - * value for \a dest. - * - * @param dest - * Variable which holds the decoding information and that will hold the - * decoded value - * @param base - * The base value for the compressed number - * @param diffbits - * The number of bits used to encode the difference from \a base - */ - void decode_compressed_number(Var& dest, uint32_t base, unsigned diffbits); - - /** - * Decode a number as described by dest.info(), and set it as value for \a - * dest. - * - * @param dest - * Variable which holds the decoding information and that will hold the - * decoded value - */ - void decode_number(Var& dest); - - bool decode_compressed_base(Varinfo info, uint32_t& base, uint32_t& diffbits); - - /** - * Decode a number as described by \a info from a compressed bufr with - * \a subsets subsets, and send the resulting variables to \a dest - */ - void decode_compressed_number(Varinfo info, unsigned subsets, std::function dest) - { - // Data field base value - uint32_t base; - - // Number of bits used for each difference value - uint32_t diffbits; - - bool missing = decode_compressed_base(info, base, diffbits); - if (missing) - { - for (unsigned i = 0; i < subsets; ++i) - dest(i, Var(info)); - } - else if (!diffbits) - { - Var var(info, info->decode_binary(base)); - for (unsigned i = 0; i < subsets; ++i) - dest(i, Var(var)); - } - else - { - Var var(info); - for (unsigned i = 0; i < subsets; ++i) - { - decode_compressed_number(var, base, diffbits); - dest(i, std::move(var)); - } - } - } - - template - void decode_string(Varinfo info, unsigned subsets, Adder& dest) - { - // Decode the base value - char str[info->bit_len / 8 + 2]; - size_t len; - bool missing = !decode_string(info->bit_len, str, len); - - // Decode the number of bits (encoded in 6 bits) for each difference - // value - uint32_t diffbits = get_bits(6); - - if (missing && diffbits == 0) - dest.add_missing(info); - else if (diffbits == 0) - { - // Add the same string to all the subsets - dest.add_same(Var(info, str)); - } else { - /* For compressed strings, the reference value must be all zeros */ - for (size_t i = 0; i < len; ++i) - if (str[i] != 0) - error_unimplemented::throwf("compressed strings with %d bit deltas have non-zero reference value", diffbits); - - /* Let's also check that the number of - * difference characters is the same length as - * the reference string */ - if (diffbits > len) - error_unimplemented::throwf("compressed strings with %zd characters have %d bit deltas (deltas should not be longer than field)", len, diffbits); - - for (unsigned i = 0; i < subsets; ++i) - { - // Set the variable value - if (decode_string(diffbits * 8, str, len)) - { - // Compute the value for this subset - dest.add_var(i, Var(info, str)); - } else { - // Missing value - dest.add_var(i, Var(info)); - } - } - } - } - - template - void decode_compressed_number(Varinfo info, unsigned subsets, Adder& dest) - { - // Data field base value - uint32_t base; - - // Number of bits used for each difference value - uint32_t diffbits; - - bool missing = decode_compressed_base(info, base, diffbits); - if (missing) - dest.add_missing(info); - else if (!diffbits) - dest.add_same(Var(info, info->decode_binary(base))); - else - { - Var var(info); - for (unsigned i = 0; i < subsets; ++i) - { - decode_compressed_number(var, base, diffbits); - dest.add_var(i, std::move(var)); - } - } - } - - /** - * Decode a number as described by \a info from a compressed bufr with - * \a subsets subsets, and send the resulting variables to \a dest - */ - void decode_compressed_number(Varinfo info, unsigned associated_field_bits, unsigned subsets, std::function dest); - - /** - * Decode a number as described by dest.info(), and set it as value for \a - * dest. The number is decoded for \a subsets compressed datasets, and an - * exception is thrown if the values differ. - * - * @param dest - * Variable which holds the decoding information and that will hold the - * decoded value - * @param subsets - * Number of subsets in the compressed data section - */ - void decode_compressed_semantic_number(Var& dest, unsigned subsets); - - /** - * Read a string from the data section - * - * @param bit_len - * Number of bits (not bytes) to read. It is normally a multiple of 8, - * and when it is not, the last character will contain the partial byte - * read. - * @retval str - * Buffer where the string is written. Must be big enough to contain the - * longest string described by info, plus 2 bytes - * @retval len - * The string length - * @return - * true if we decoded a real string, false if we decoded a missing string - * value - */ - bool decode_string(unsigned bit_len, char* str, size_t& len); - - /** - * Decode a string as described by dest.info(), ad set it as value for \a - * dest. - * - * It is assumed that \a dest is not set, therefore in case we decode a - * missing value, \a dest will not be touched. - * - * @param dest - * Variable which holds the decoding information and that will hold the - * decoded value - */ - void decode_string(Var& dest); - - /** - * Decode a string as described by dest.info(), and set it as value for \a - * dest. The string is decoded for \a subsets compressed datasets, and an - * exception is thrown if the values differ. - * - * @param dest - * Variable which holds the decoding information and that will hold the - * decoded value - * @param subsets - * Number of subsets in the compressed data section - */ - void decode_string(Var& dest, unsigned subsets); - - /** - * Decode a string as described by \a info from a compressed bufr with \a - * subsets subsets, and send the resulting variables to \a dest - */ - void decode_string(Varinfo info, unsigned subsets, std::function dest); - - /** - * Decode a generic binary value as-is, as described by dest.info(), ad set - * it as value for \a dest. - * - * It is assumed that \a dest is not set, therefore in case we decode a - * missing value, \a dest will not be touched. - * - * @param dest - * Variable which holds the decoding information and that will hold the - * decoded value - */ - void decode_binary(Var& dest); - - /** - * Decode an uncompressed bitmap of \a size bits. - * - * The result will be a string \a size bytes long, with a '+' where the - * bitmap reports that data is present, and a '-' where the bitmap reports - * that data is not present. - */ - std::string decode_uncompressed_bitmap(unsigned size) - { - std::string buf; - buf.resize(size); - for (unsigned i = 0; i < size; ++i) - { - uint32_t val = get_bits(1); - buf[i] = (val == 0) ? '+' : '-'; - } - return buf; - } - - /** - * Decode a "compressed" bitmap of \a size bits. - * - * The result will be a string \a size bytes long, with a '+' where the - * bitmap reports that data is present, and a '-' where the bitmap reports - * that data is not present. - * - * It would be more correct to say that it decodes a bitmap from a - * compressed BUFR message, because bitmaps in compressed messages are - * actually encoded with 7 bits per bit instead of one, because after each - * bit they need to send 6 bits saying that it will be followed by 0 bits - * of difference values. - */ - std::string decode_compressed_bitmap(unsigned size) - { - std::string buf; - buf.resize(size); - for (unsigned i = 0; i < size; ++i) - { - uint32_t val = get_bits(1); - buf[i] = (val == 0) ? '+' : '-'; - // Decode the number of bits (encoded in 6 bits) of difference - // values. It's odd to repeat this for each bit in the bitmap, but - // that's how things are transmitted and it's somewhat consistent - // with how data compression is specified - val = get_bits(6); - // If compressed, ensure that the difference bits are 0 and they are - // not trying to transmit odd things like delta bitmaps - if (val != 0) - parse_error("bitmap entry %u declares %u difference bits, but we only support 0", i, val); - } - return buf; - } -}; - -/** * Binary buffer with bit-level append operations */ struct BufrOutput diff -Nru wreport-3.6/wreport/buffers/bufr-test.cc wreport-3.15/wreport/buffers/bufr-test.cc --- wreport-3.6/wreport/buffers/bufr-test.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/buffers/bufr-test.cc 2018-05-14 15:34:17.000000000 +0000 @@ -1,4 +1,4 @@ -#include "tests.h" +#include "wreport/tests.h" #include "bufr.h" using namespace wreport; diff -Nru wreport-3.6/wreport/bufr/decoder.cc wreport-3.15/wreport/bufr/decoder.cc --- wreport-3.6/wreport/bufr/decoder.cc 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/bufr/decoder.cc 2018-07-26 09:31:32.000000000 +0000 @@ -0,0 +1,729 @@ +#include "decoder.h" +#include "trace.h" +#include "wreport/vartable.h" +#include + +namespace wreport { +namespace bufr { + +// Return a value with bitlen bits set to 1 +static inline uint32_t all_ones(int bitlen) +{ + return ((1 << (bitlen - 1))-1) | (1 << (bitlen - 1)); +} + + +Decoder::Decoder(const std::string& buf, const char* fname, size_t offset, BufrBulletin& out) + : in(buf), out(out) +{ + in.fname = fname; + in.start_offset = offset; +} + +void Decoder::read_options(const BufrCodecOptions& opts) +{ + conf_add_undef_attrs = opts.decode_adds_undef_attrs; +} + +void Decoder::decode_sec1ed3() +{ + // master table number in sec1[3] + out.master_table_number = in.read_byte(1, 3); + // has_optional in sec1[7] + // Once we know if the optional section is available, we can scan + // section lengths for the rest of the message + in.scan_other_sections(in.read_byte(1, 7) & 0x80); + optional_section_length = in.sec[3] - in.sec[2]; + if (optional_section_length) + optional_section_length -= 4; + // subcentre in sec1[4] + out.originating_subcentre = in.read_byte(1, 4); + // centre in sec1[5] + out.originating_centre = in.read_byte(1, 5); + // Update sequence number sec1[6] + out.update_sequence_number = in.read_byte(1, 6); + out.master_table_version_number = in.read_byte(1, 10); + out.master_table_version_number_local = in.read_byte(1, 11); + out.data_category = in.read_byte(1, 8); + out.data_subcategory = 0xff; + out.data_subcategory_local = in.read_byte(1, 9); + + out.rep_year = in.read_byte(1, 12); + // Fix the century with a bit of euristics + if (out.rep_year > 50) + out.rep_year += 1900; + else + out.rep_year += 2000; + out.rep_month = in.read_byte(1, 13); + out.rep_day = in.read_byte(1, 14); + out.rep_hour = in.read_byte(1, 15); + out.rep_minute = in.read_byte(1, 16); + if (in.read_byte(1, 17) != 0) + out.rep_year = in.read_byte(1, 17) * 100 + (out.rep_year % 100); +} + +void Decoder::decode_sec1ed4() +{ + // master table number in sec1[3] + out.master_table_number = in.read_byte(1, 3); + // centre in sec1[4-5] + out.originating_centre = in.read_number(1, 4, 2); + // subcentre in sec1[6-7] + out.originating_subcentre = in.read_number(1, 6, 2); + // update sequence number sec1[8] + out.update_sequence_number = in.read_byte(1, 8); + // has_optional in sec1[9] + // Once we know if the optional section is available, we can scan + // section lengths for the rest of the message + in.scan_other_sections(in.read_byte(1, 9) & 0x80); + optional_section_length = in.sec[3] - in.sec[2]; + if (optional_section_length) + { + if (optional_section_length >= 4) + optional_section_length -= 4; + else + error_consistency::throwf("Section 2 length is %u but, if present, it must be at least 4", optional_section_length); + } + // category in sec1[10] + out.data_category = in.read_byte(1, 10); + // international data sub-category in sec1[11] + out.data_subcategory = in.read_byte(1, 11); + // local data sub-category in sec1[12] + out.data_subcategory_local = in.read_byte(1, 12); + // version number of master table in sec1[13] + out.master_table_version_number = in.read_byte(1, 13); + // version number of local table in sec1[14] + out.master_table_version_number_local = in.read_byte(1, 14); + // year in sec1[15-16] + out.rep_year = in.read_number(1, 15, 2); + // month in sec1[17] + out.rep_month = in.read_byte(1, 17); + // day in sec1[18] + out.rep_day = in.read_byte(1, 18); + // hour in sec1[19] + out.rep_hour = in.read_byte(1, 19); + // minute in sec1[20] + out.rep_minute = in.read_byte(1, 20); + // sec in sec1[21] + out.rep_second = in.read_byte(1, 21); +} + +/* Decode the message header only */ +void Decoder::decode_header() +{ + in.check_available_data(0, 8, "section 0 of BUFR message (indicator section)"); + + // Read BUFR section 0 (Indicator section) + if (memcmp(in.data + in.sec[0], "BUFR", 4) != 0) + in.parse_error(0, 0, "data does not start with BUFR header (\"%.4s\" was read instead)", in.data + in.sec[0]); + + // Check the BUFR edition number + out.edition_number = in.read_byte(0, 7); + if (out.edition_number != 2 && out.edition_number != 3 && out.edition_number != 4) + in.parse_error(0, 7, "Only BUFR edition 2, 3, and 4 are supported (this message is edition %d)", out.edition_number); + + // Looks like a BUFR, scan section starts + in.scan_lead_sections(); + + // Read bufr section 1 (Identification section) + in.check_available_message_data(1, 0, out.edition_number == 4 ? 22 : 18, "section 1 of BUFR message (identification section)"); + + switch (out.edition_number) + { + case 2: decode_sec1ed3(); break; + case 3: decode_sec1ed3(); break; + case 4: decode_sec1ed4(); break; + default: + error_consistency::throwf("BUFR edition is %d, but I can only decode 2, 3 and 4", out.edition_number); + } + + TRACE("BUFR:edition %d, optional section %ub, update sequence number %d\n", + out.edition_number, optional_section_length, out.update_sequence_number); + TRACE(" origin %d.%d tables %d.%d type %d.%d %04d-%02d-%02d %02d:%02d\n", + out.originating_centre, out.originating_subcentre, + out.master_table_number, out.master_table_version_number_local, + out.data_category, out.data_subcategory, + out.rep_year, out.rep_month, out.rep_day, out.rep_hour, out.rep_minute); + + // Read BUFR section 2 (Optional section) + if (optional_section_length) + { + in.check_available_section_data(2, 0, 3, "section 2 of BUFR message (optional section length)"); + unsigned s2_length = in.read_number(2, 0, 3); + in.check_available_section_data(2, 0, s2_length, "section 2 of BUFR message (optional section)"); + if (s2_length < 4) + error_consistency::throwf("Optional section length is %u but it must be at least 4", s2_length); + out.optional_section = std::string((const char*)in.data + in.sec[2] + 4, s2_length - 4); + } + + /* Read BUFR section 3 (Data description section) */ + if (in.sec[4] - in.sec[3] < 7) + error_consistency::throwf("Data descriptor section length is %u but it must be at least 7", in.sec[4] - in.sec[3]); + in.check_available_section_data(3, 0, 8, "section 3 of BUFR message (data description section)"); + expected_subsets = in.read_number(3, 4, 2); + out.compression = (in.read_byte(3, 6) & 0x40) ? 1 : 0; + unsigned descriptor_count = (in.sec[4] - in.sec[3] - 7) / 2; + in.check_available_section_data(3, 7, descriptor_count * 2, "data descriptor list"); + for (unsigned i = 0; i < descriptor_count; i++) + out.datadesc.push_back((Varcode)in.read_number(3, 7 + i * 2, 2)); + TRACE(" s3length %d subsets %zd observed %d compression %d byte7 %x\n", + in.sec[4] - in.sec[3], expected_subsets, (in.read_byte(3, 6) & 0x80) ? 1 : 0, + out.compression, in.read_byte(3, 6)); + /* + IFTRACE{ + TRACE(" -> data descriptor section: "); + bufrex_opcode_print(msg->datadesc, stderr); + TRACE("\n"); + } + */ + // Once we filled the Bulletin header info, load decoding tables and allocate subsets + out.load_tables(); +} + +void Decoder::decode_data() +{ + out.obtain_subset(expected_subsets - 1); + + /* Read BUFR section 4 (Data section) */ + TRACE(" decode_data:section 4 is %d bytes long (%02x %02x %02x %02x)\n", + in.read_number(4, 0, 3), + in.read_byte(4, 0), + in.read_byte(4, 1), + in.read_byte(4, 2), + in.read_byte(4, 3)); + + if (out.compression) + { + // Run only once + CompressedDecoderTarget target(in, out); + std::unique_ptr dec; + if (verbose_output) + dec.reset(new VerboseDataSectionDecoder(out, target, verbose_output)); + else + dec.reset(new DataSectionDecoder(out, target)); + dec->associated_field.skip_missing = !conf_add_undef_attrs; + dec->run(); + } else { + // Run once per subset + for (unsigned i = 0; i < out.subsets.size(); ++i) + { + UncompressedDecoderTarget target(in, out.obtain_subset(i)); + std::unique_ptr dec; + if (verbose_output) + dec.reset(new VerboseDataSectionDecoder(out, target, verbose_output)); + else + dec.reset(new DataSectionDecoder(out, target)); + dec->associated_field.skip_missing = !conf_add_undef_attrs; + dec->run(); + } + } + + IFTRACE { + if (in.bits_left() > 32) + { + fprintf(stderr, "The data section of %s:%zd still contains %d unparsed bits\n", + in.fname, in.start_offset, in.bits_left() - 32); + /* + err = dba_error_parse(msg->file->name, POS + vec->cursor, + "the data section still contains %d unparsed bits", + bitvec_bits_left(vec)); + goto fail; + */ + } + } + + /* Read BUFR section 5 (Data section) */ + in.check_available_section_data(5, 0, 4, "section 5 of BUFR message (end section)"); + + if (memcmp(in.data + in.sec[5], "7777", 4) != 0) + in.parse_error(5, 0, "section 5 does not contain '7777'"); + + for (unsigned i = 0; i < 5; ++i) + out.section_end[i] = in.sec[i + 1]; + out.section_end[5] = out.section_end[4] + 4; + + //if (subsets_no != out.subsets.size()) + // parse_error(sec5, "header advertised %u subsets but only %zd found", subsets_no, out.subsets.size()); +} + + +/* + * UncompressedDecoderTarget + */ + +UncompressedDecoderTarget::UncompressedDecoderTarget(Input& in, Subset& out) + : DecoderTarget(in), out(out) +{ +} + +const Subset& UncompressedDecoderTarget::reference_subset() const { return out; } + +Varinfo UncompressedDecoderTarget::lookup_info(unsigned pos) const +{ + return out[pos].info(); +} + +Var UncompressedDecoderTarget::decode_uniform_b_value(Varinfo info) +{ + Var var(info); + switch (info->type) + { + case Vartype::String: + in.decode_string(var); + break; + case Vartype::Binary: + in.decode_binary(var); + break; + case Vartype::Integer: + case Vartype::Decimal: + in.decode_number(var); + break; + } + return var; +} + +const Var& UncompressedDecoderTarget::decode_and_add_to_all(Varinfo info) +{ + out.store_variable(decode_uniform_b_value(info)); + return out.back(); +} + +const Var& UncompressedDecoderTarget::decode_and_add_bitmap(const Tables& tables, Varcode code, unsigned bitmap_size) +{ + // Read the bitmap + std::string buf = in.decode_uncompressed_bitmap(bitmap_size); + + // Create a single use varinfo to store the bitmap + Varinfo info = tables.get_bitmap(code, buf); + + // Store the bitmap + out.store_variable(Var(info, buf)); + + return out.back(); +} + +void UncompressedDecoderTarget::decode_and_set_attribute(Varinfo info, unsigned pos) +{ + Var var = decode_uniform_b_value(info); + TRACE(" define_attribute adding var %01d%02d%03d %s as attribute to %01d%02d%03d\n", + WR_VAR_FXY(var.code()), var.enqc(), WR_VAR_FXY(out[pos].code())); + if (!var.isset()) + return; + out[pos].seta(std::move(var)); +} + +void UncompressedDecoderTarget::decode_and_add_b_value(Varinfo info) +{ + Var var = decode_uniform_b_value(info); + out.store_variable(var); + IFTRACE { + TRACE(" define_variable decoded: "); + out.back().print(stderr); + } +} + +void UncompressedDecoderTarget::decode_and_add_b_value_with_associated_field(Varinfo info, const bulletin::AssociatedField& field) +{ + /// If set, it is the associated field for the next variable to be decoded + TRACE("decode_b_data:reading %d bits of C04 information\n", associated_field.bit_count); + uint32_t val = in.get_bits(field.bit_count); + TRACE("decode_b_data:read C04 information %x\n", val); + auto cur_associated_field = field.make_attribute(val); + + Var var = decode_uniform_b_value(info); + out.store_variable(var); + IFTRACE { + TRACE(" define_variable decoded: "); + out.back().print(stderr); + } + if (cur_associated_field.get()) + { + IFTRACE { + TRACE(" define_variable with associated field: "); + cur_associated_field->print(stderr); + } + out.back().seta(std::move(cur_associated_field)); + } +} + +void UncompressedDecoderTarget::decode_and_add_raw_character_data(Varinfo info) +{ + std::string buf; + buf.resize(info->len); + TRACE("decode_c_data:character data %d long\n", cdatalen); + for (unsigned i = 0; i < info->len; ++i) + { + uint32_t bitval = in.get_bits(8); + TRACE("decode_c_data:decoded character %d %c\n", (int)bitval, (char)bitval); + buf[i] = bitval; + } + + // Add as C variable to the subset + + // Store the character data + Var cdata(info, buf); + out.store_variable(cdata); + + TRACE("decode_c_data:decoded string %s\n", buf.c_str()); +} + +void UncompressedDecoderTarget::print_last_variable_added(FILE* out) +{ + this->out.back().format(out, "-"); +} + +void UncompressedDecoderTarget::print_last_attribute_added(FILE* out, Varcode code, unsigned pos) +{ + auto attr = this->out[pos].enqa(code); + if (attr) + attr->format(out, "-"); + else + putc('-', out); +} + + +/* + * CompressedDecoderTarget + */ + +CompressedDecoderTarget::CompressedDecoderTarget(Input& in, Bulletin& out) + : DecoderTarget(in), out(out), subset_count(out.subsets.size()) +{ +} + +const Subset& CompressedDecoderTarget::reference_subset() const { return out.subsets[0]; } + +Varinfo CompressedDecoderTarget::lookup_info(unsigned pos) const +{ + return out.subset(0)[pos].info(); +} + +Var CompressedDecoderTarget::decode_uniform_b_value(Varinfo info) +{ + Var var(info); + switch (info->type) + { + case Vartype::String: + in.decode_string(var, subset_count); + break; + case Vartype::Binary: + throw error_unimplemented("decode_b_binary TODO"); + case Vartype::Integer: + case Vartype::Decimal: + in.decode_compressed_semantic_number(var, subset_count); + break; + } + return var; +} + +void CompressedDecoderTarget::decode_b_value(Varinfo info, std::function dest) +{ + switch (info->type) + { + case Vartype::String: + in.decode_string(info, subset_count, dest); + break; + case Vartype::Binary: + throw error_unimplemented("decode_b_binary TODO"); + case Vartype::Integer: + case Vartype::Decimal: + in.decode_compressed_number(info, subset_count, dest); + break; + } +} + +const Var& CompressedDecoderTarget::decode_and_add_to_all(Varinfo info) +{ + Var res(decode_uniform_b_value(info)); + for (unsigned i = 0; i < subset_count; ++i) + out.subsets[i].store_variable(res); + return out.subsets[0].back(); +} + +const Var& CompressedDecoderTarget::decode_and_add_bitmap(const Tables& tables, Varcode code, unsigned bitmap_size) +{ + // Read the bitmap + std::string buf = in.decode_compressed_bitmap(bitmap_size); + + // Create a single use varinfo to store the bitmap + Varinfo info = tables.get_bitmap(code, buf); + + // Store the bitmap + Var bmp(info, buf); + for (unsigned i = 0; i < subset_count; ++i) + out.subsets[i].store_variable(bmp); + + return out.subsets[0].back(); +} + +void CompressedDecoderTarget::decode_and_set_attribute(Varinfo info, unsigned pos) +{ + decode_b_value(info, [&](unsigned idx, Var&& var) { + TRACE("define_attribute:seta subset[%u][%u] (%01d%02d%03d) %01d%02d%03d %s\n", idx, pos, WR_VAR_FXY(out.subsets[idx][pos].code()), WR_VAR_FXY(var.code()), var.enq("-")); + if (!var.isset()) + return; + out.subsets[idx][pos].seta(std::move(var)); + }); +} + +void CompressedDecoderTarget::decode_and_add_b_value(Varinfo info) +{ + DispatchToSubsets dest(out, subset_count); + switch (info->type) + { + case Vartype::String: + in.decode_string(info, subset_count, dest); + break; + case Vartype::Binary: + throw error_unimplemented("decode_b_binary TODO"); + case Vartype::Integer: + case Vartype::Decimal: + in.decode_compressed_number(info, subset_count, dest); + break; + } +} + +void CompressedDecoderTarget::decode_and_add_b_value_with_associated_field(Varinfo info, const bulletin::AssociatedField& field) +{ + DispatchToSubsets dest(out, subset_count); + switch (info->type) + { + case Vartype::String: + in.decode_string(info, subset_count, dest); + break; + case Vartype::Binary: + throw error_unimplemented("decode_b_binary TODO"); + case Vartype::Integer: + case Vartype::Decimal: + in.decode_compressed_number(info, field, subset_count, [&](unsigned subset_no, Var&& var) { + dest.add_var(subset_no, std::move(var)); + }); + break; + } +} + +void CompressedDecoderTarget::decode_and_add_raw_character_data(Varinfo info) +{ + // TODO: if compressed, extract the data from each subset? Store it in each dataset? + error_unimplemented::throwf("C05%03d character data found in compressed message and it is not clear how it should be handled", WR_VAR_Y(info->code)); +} + +void CompressedDecoderTarget::print_last_variable_added(FILE* out) +{ + for (const auto& s: this->out.subsets) + { + s.back().format(out, "-"); + putc(' ', out); + } +} + +void CompressedDecoderTarget::print_last_attribute_added(FILE* out, Varcode code, unsigned pos) +{ + for (const auto& s: this->out.subsets) + { + auto attr = s[pos].enqa(code); + if (attr) + attr->format(out, "-"); + else + putc('-', out); + putc(' ', out); + } +} + + +/* + * DataSectionDecoder + */ + +DataSectionDecoder::DataSectionDecoder(Bulletin& bulletin, DecoderTarget& target) + : Interpreter(bulletin.tables, bulletin.datadesc), target(target) +{ +} + +unsigned DataSectionDecoder::define_bitmap_delayed_replication_factor(Varinfo info) +{ + Var rep_count = target.decode_uniform_b_value(info); + return rep_count.enqi(); +} + +unsigned DataSectionDecoder::define_delayed_replication_factor(Varinfo info) +{ + return target.decode_and_add_to_all(info).enqi(); +} + +unsigned DataSectionDecoder::define_associated_field_significance(Varinfo info) +{ + return target.decode_and_add_to_all(info).enq(63); +} + +void DataSectionDecoder::define_bitmap(unsigned bitmap_size) +{ + TRACE("define_bitmap %d\n", bitmap_size); + + const Var& bmp = target.decode_and_add_bitmap(tables, bitmaps.pending_definitions, bitmap_size); + + IFTRACE { + TRACE("Decoded bitmap count %u: ", bitmap_size); + bmp.print(stderr); + TRACE("\n"); + } + + bitmaps.define(bmp, target.reference_subset()); +} + +void DataSectionDecoder::define_attribute(Varinfo info, unsigned pos) +{ + target.decode_and_set_attribute(info, pos); +} + +void DataSectionDecoder::define_substituted_value(unsigned pos) +{ + Varinfo info = target.lookup_info(pos); + target.decode_and_set_attribute(info, pos); +} + +void DataSectionDecoder::define_variable(Varinfo info) +{ + target.decode_and_add_b_value(info); +} + +void DataSectionDecoder::define_variable_with_associated_field(Varinfo info) +{ + target.decode_and_add_b_value_with_associated_field(info, associated_field); +} + +void DataSectionDecoder::define_raw_character_data(Varcode code) +{ + // Create a single use varinfo to store the bitmap + Varinfo info = tables.get_chardata(code, WR_VAR_Y(code)); + target.decode_and_add_raw_character_data(info); +} + + +/* + * VerboseDataSectionDecoder + */ + +VerboseDataSectionDecoder::VerboseDataSectionDecoder(Bulletin& bulletin, DecoderTarget& target, FILE* out) + : DataSectionDecoder(bulletin, target), out(out) +{ +} + +void VerboseDataSectionDecoder::print_lead(Varcode code) +{ + fprintf(out, "%*s%d%02d%03d ", + indent, "", WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code)); +} + +void VerboseDataSectionDecoder::print_lead_continued() +{ + fprintf(out, "%*s ", indent, ""); +} + +void VerboseDataSectionDecoder::b_variable(Varcode code) +{ + print_lead(code); + if (tables.btable) + { + if (tables.btable->contains(code)) + { + Varinfo info = tables.btable->query(code); + fprintf(out, "%s[%s]", info->desc, info->unit); + } else + fprintf(out, "(missing in B table %s)", tables.btable->pathname().c_str()); + } + putc('\n', out); + DataSectionDecoder::b_variable(code); +} + +void VerboseDataSectionDecoder::c_modifier(Varcode code, Opcodes& next) +{ + print_lead(code); + Interpreter::print_c_modifier(out, code, next); + DataSectionDecoder::c_modifier(code, next); +} + +void VerboseDataSectionDecoder::r_replication(Varcode code, Varcode delayed_code, const Opcodes& ops) +{ + print_lead(code); + unsigned group = WR_VAR_X(code); + unsigned count = WR_VAR_Y(code); + fprintf(out, "replicate %u descriptors", group); + if (count) + fprintf(out, " %u times\n", count); + else + fprintf(out, " (delayed %d%02d%03d) times\n", + WR_VAR_F(delayed_code), WR_VAR_X(delayed_code), WR_VAR_Y(delayed_code)); + indent += indent_step; + DataSectionDecoder::r_replication(code, delayed_code, ops); + indent -= indent_step; +} + +void VerboseDataSectionDecoder::run_d_expansion(Varcode code) +{ + print_lead(code); + fputs(" (group)\n", out); + indent += indent_step; + Interpreter::run_d_expansion(code); + indent -= indent_step; +} + +unsigned VerboseDataSectionDecoder::define_delayed_replication_factor(Varinfo info) +{ + unsigned res = DataSectionDecoder::define_delayed_replication_factor(info); + print_lead_continued(); + fprintf(out, "delayed replication factor: %u\n", res); + return res; +} +unsigned VerboseDataSectionDecoder::define_associated_field_significance(Varinfo info) +{ + return DataSectionDecoder::define_associated_field_significance(info); + // TODO: print results +} +unsigned VerboseDataSectionDecoder::define_bitmap_delayed_replication_factor(Varinfo info) +{ + return DataSectionDecoder::define_bitmap_delayed_replication_factor(info); + // TODO: print results +} +void VerboseDataSectionDecoder::define_bitmap(unsigned bitmap_size) +{ + DataSectionDecoder::define_bitmap(bitmap_size); + // TODO: print results +} +void VerboseDataSectionDecoder::define_attribute(Varinfo info, unsigned pos) +{ + DataSectionDecoder::define_attribute(info, pos); + print_lead_continued(); + fprintf(out, "attribute %d%02d%03d %s\n", WR_VAR_FXY(info->code), info->desc); + Varinfo pos_info = target.lookup_info(pos); + print_lead_continued(); + fprintf(out, "at position %u: %d%02d%03d %s\n", pos, WR_VAR_FXY(pos_info->code), pos_info->desc); + print_lead_continued(); + target.print_last_attribute_added(out, info->code, pos); + putc('\n', out); +} +void VerboseDataSectionDecoder::define_substituted_value(unsigned pos) +{ + DataSectionDecoder::define_substituted_value(pos); + // TODO: print results +} +void VerboseDataSectionDecoder::define_variable(Varinfo info) +{ + DataSectionDecoder::define_variable(info); + print_lead_continued(); + target.print_last_variable_added(out); + putc('\n', out); +} +void VerboseDataSectionDecoder::define_variable_with_associated_field(Varinfo info) +{ + DataSectionDecoder::define_variable_with_associated_field(info); + // TODO: print results +} +void VerboseDataSectionDecoder::define_raw_character_data(Varcode code) +{ + DataSectionDecoder::define_raw_character_data(code); + // TODO: print results +} + +} +} diff -Nru wreport-3.6/wreport/bufr/decoder.h wreport-3.15/wreport/bufr/decoder.h --- wreport-3.6/wreport/bufr/decoder.h 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/bufr/decoder.h 2018-05-14 15:34:17.000000000 +0000 @@ -0,0 +1,221 @@ +#ifndef WREPORT_BUFR_DECODER_H +#define WREPORT_BUFR_DECODER_H + +#include +#include +#include +#include + +namespace wreport { +namespace bufr { +struct DispatchToSubsets; + +struct Decoder +{ + /// Input data + Input in; + /* Output decoded variables */ + BufrBulletin& out; + /// Number of expected subsets (read in decode_header, used in decode_data) + size_t expected_subsets; + /// True if undefined attributes are added to the output, else false + bool conf_add_undef_attrs = false; + /// Optional section length decoded from the message + unsigned optional_section_length = 0; + /// If set, be verbose and print a trace of decoding to the given file + FILE* verbose_output = nullptr; + + Decoder(const std::string& buf, const char* fname, size_t offset, BufrBulletin& out); + + void read_options(const BufrCodecOptions& opts); + + void decode_sec1ed3(); + void decode_sec1ed4(); + + /* Decode the message header only */ + void decode_header(); + + /* Decode message data section after the header has been decoded */ + void decode_data(); +}; + +struct DecoderTarget +{ + /// Input buffer + Input& in; + + DecoderTarget(Input& in) : in(in) {} + virtual ~DecoderTarget() {} + + /** + * Return the reference to a subset that is receiving the data currently + * decoded. + * + * For uncompressed decoders, this is the current subset. For compressed + * decoders, it is the first subset. + */ + virtual const Subset& reference_subset() const = 0; + + /** + * Return information about a value previously stored at the given position + */ + virtual Varinfo lookup_info(unsigned pos) const = 0; + + /** + * Decode a value that must always be the same across all datasets. + * + * Do not add it to the output. + * + * @returns the decoded value + */ + virtual Var decode_uniform_b_value(Varinfo info) = 0; + + /** + * Decode and add the same value to all datasets, return a reference to one + * of the variables added + */ + virtual const Var& decode_and_add_to_all(Varinfo info) = 0; + + virtual const Var& decode_and_add_bitmap(const Tables& tables, Varcode code, unsigned bitmap_size) = 0; + + /** + * Decode an attribute with the given description, and add it to data at + * position pos + */ + virtual void decode_and_set_attribute(Varinfo info, unsigned pos) = 0; + + /** + * Decode a B-table value and add its value(s) to the target subset(s) + */ + virtual void decode_and_add_b_value(Varinfo info) = 0; + + /** + * Decode a B-table value with associated field, and add its value(s) to + * the target subset(s) + */ + virtual void decode_and_add_b_value_with_associated_field(Varinfo info, const bulletin::AssociatedField& field) = 0; + + /** + * Decode raw character data described by \a code and add it to the target + * subset(s) + */ + virtual void decode_and_add_raw_character_data(Varinfo info) = 0; + + /// Print the value(s) of the last variable(s) added to \a out + virtual void print_last_variable_added(FILE* out) = 0; + + /// Print the value(s) of the last attributes(s) with the given \a code added to \a out + virtual void print_last_attribute_added(FILE* out, Varcode code, unsigned pos) = 0; +}; + +struct UncompressedDecoderTarget : public DecoderTarget +{ + /// Subset where decoded variables go + Subset& out; + + UncompressedDecoderTarget(Input& in, Subset& out); + + const Subset& reference_subset() const override; + Varinfo lookup_info(unsigned pos) const override; + Var decode_uniform_b_value(Varinfo info) override; + const Var& decode_and_add_to_all(Varinfo info) override; + const Var& decode_and_add_bitmap(const Tables& tables, Varcode code, unsigned bitmap_size) override; + void decode_and_set_attribute(Varinfo info, unsigned pos) override; + void decode_and_add_b_value(Varinfo info) override; + void decode_and_add_b_value_with_associated_field(Varinfo info, const bulletin::AssociatedField& field) override; + void decode_and_add_raw_character_data(Varinfo info) override; + + void print_last_variable_added(FILE* out) override; + void print_last_attribute_added(FILE* out, Varcode code, unsigned pos) override; +}; + +struct CompressedDecoderTarget : public DecoderTarget +{ + /// Output bulletin + Bulletin& out; + + /// Number of subsets in data section + unsigned subset_count; + + CompressedDecoderTarget(Input& in, Bulletin& out); + + const Subset& reference_subset() const override; + Varinfo lookup_info(unsigned pos) const override; + Var decode_uniform_b_value(Varinfo info) override; + const Var& decode_and_add_to_all(Varinfo info) override; + const Var& decode_and_add_bitmap(const Tables& tables, Varcode code, unsigned bitmap_size) override; + void decode_and_set_attribute(Varinfo info, unsigned pos) override; + void decode_and_add_b_value(Varinfo info) override; + void decode_and_add_b_value_with_associated_field(Varinfo info, const bulletin::AssociatedField& field) override; + void decode_and_add_raw_character_data(Varinfo info) override; + + void print_last_variable_added(FILE* out) override; + void print_last_attribute_added(FILE* out, Varcode code, unsigned pos) override; + +protected: + void decode_b_value(Varinfo info, std::function dest); +}; + +struct DataSectionDecoder : public bulletin::Interpreter +{ + DecoderTarget& target; + + DataSectionDecoder(Bulletin& bulletin, DecoderTarget& target); + + unsigned define_delayed_replication_factor(Varinfo info) override; + unsigned define_associated_field_significance(Varinfo info) override; + unsigned define_bitmap_delayed_replication_factor(Varinfo info) override; + void define_bitmap(unsigned bitmap_size) override; + void define_attribute(Varinfo info, unsigned pos) override; + void define_substituted_value(unsigned pos) override; + void define_variable(Varinfo info) override; + void define_variable_with_associated_field(Varinfo info) override; + void define_raw_character_data(Varcode code) override; +}; + +struct VerboseDataSectionDecoder : public DataSectionDecoder +{ +protected: + /** + * Print line lead (indentation and formatted code) + * + * @param code + * Code to format in the line lead + */ + void print_lead(Varcode code); + void print_lead_continued(); + +public: + FILE* out; + + /** + * Current indent level + * + * It defaults to 0 in a newly created Printer. You can set it to some + * other value to indent all the output by the given amount of spaces + */ + unsigned indent = 0; + + /// How many spaces in an indentation level + unsigned indent_step = 2; + + VerboseDataSectionDecoder(Bulletin& bulletin, DecoderTarget& target, FILE* out); + + void b_variable(Varcode code) override; + void c_modifier(Varcode code, Opcodes& next) override; + void r_replication(Varcode code, Varcode delayed_code, const Opcodes& ops) override; + void run_d_expansion(Varcode code) override; + unsigned define_delayed_replication_factor(Varinfo info) override; + unsigned define_associated_field_significance(Varinfo info) override; + unsigned define_bitmap_delayed_replication_factor(Varinfo info) override; + void define_bitmap(unsigned bitmap_size) override; + void define_attribute(Varinfo info, unsigned pos) override; + void define_substituted_value(unsigned pos) override; + void define_variable(Varinfo info) override; + void define_variable_with_associated_field(Varinfo info) override; + void define_raw_character_data(Varcode code) override; +}; + +} +} +#endif diff -Nru wreport-3.6/wreport/bufr/decoder-test.cc wreport-3.15/wreport/bufr/decoder-test.cc --- wreport-3.6/wreport/bufr/decoder-test.cc 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/bufr/decoder-test.cc 2018-09-19 13:06:24.000000000 +0000 @@ -0,0 +1,817 @@ +#include "wreport/tests.h" +#include + +using namespace wreport; +using namespace wreport::tests; +using namespace std; + +namespace { + +typedef tests::TestCodec TestBufr; + +class Tests : public TestCase +{ + using TestCase::TestCase; + + void declare_test(std::string fname, std::function check_contents) + { + add_method(fname, [=]() { + TestBufr test(fname); + test.check_contents = check_contents; + wassert(test.run()); + }); + }; + + void declare_test_decode_fail(std::string fname, std::string errmsg) + { + add_method(fname, [=]() { + // Read the whole contents of the test file + std::string raw = wcallchecked(slurpfile(fname)); + + bool failed = true; + try { + BufrBulletin::decode(raw, fname.c_str()); + failed = false; + } catch (std::exception& e) { + wassert(actual(e.what()).contains(errmsg)); + } + wassert(actual(failed).istrue()); + }); + } + + void register_tests() override + { + add_method("bufr/corrupted.bufr", []() { + // Corrupted BUFR + + // Read the whole contents of the test file + std::string raw1 = tests::slurpfile("bufr/corrupted.bufr"); + + // Decode the original contents + try { + BufrBulletin::decode(raw1, "bufr/corrupted.bufr"); + } catch (std::exception& e) { + wassert(actual(e.what()).contains("Only BUFR edition 2, 3, and 4 are supported (this message is edition 47)")); + } + }); + + declare_test("bufr/bufr1", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 1); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 21); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 35u); + + wassert(actual_varcode(s[9].code()) == WR_VAR(0, 5, 2)); + wassert(actual(s[9].enqd()) == 68.27); + wassert(actual_varcode(s[10].code()) == WR_VAR(0, 6, 2)); + wassert(actual(s[10].enqd()) == 9.68); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(msg.section_end[0]) == 8u); + wassert(actual(msg.section_end[1]) == 26u); + wassert(actual(msg.section_end[2]) == 78u); + wassert(actual(msg.section_end[3]) == 102u); + wassert(actual(msg.section_end[4]) == 178u); + wassert(actual(msg.section_end[5]) == 182u); + }); + + declare_test("bufr/bufr2", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 1); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 21); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 35u); + + wassert(actual_varcode(s[9].code()) == WR_VAR(0, 5, 2)); + wassert(actual(s[9].enqd()) == 43.02); + wassert(actual_varcode(s[10].code()) == WR_VAR(0, 6, 2)); + wassert(actual(s[10].enqd()) == -12.45); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs0-1.22.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 0); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 1); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 52u); + + wassert(actual_varcode(s[27].code()) == WR_VAR(0, 20, 13)); + wassert(actual(s[27].enqd()) == 250.0); + wassert(actual_varcode(s[34].code()) == WR_VAR(0, 20, 13)); + wassert(actual(s[34].enqd()) == 320.0); + wassert(actual_varcode(s[38].code()) == WR_VAR(0, 20, 13)); + wassert(actual(s[38].enqd()) == 620.0); + wassert(actual_varcode(s[42].code()) == WR_VAR(0, 20, 13)); + wassert(actual(s[42].enqd()) == 920.0); + wassert(actual_varcode(s[46].code()) == WR_VAR(0, 20, 13)); + wassert(actual(s[46].isset()).isfalse()); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs0-3.504.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 0); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 3); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 52u); + + wassert(actual_varcode(s[28].code()) == WR_VAR(0, 20, 12)); + wassert(actual(s[28].enqd()) == 37.0); + wassert(actual_varcode(s[29].code()) == WR_VAR(0, 20, 12)); + wassert(actual(s[29].enqd()) == 22.0); + wassert(actual_varcode(s[30].code()) == WR_VAR(0, 20, 12)); + wassert(actual(s[30].enqd()) == 60.0); + wassert(actual_varcode(s[33].code()) == WR_VAR(0, 20, 12)); + wassert(actual(s[33].enqd()) == 7.0); + wassert(actual_varcode(s[37].code()) == WR_VAR(0, 20, 12)); + wassert(actual(s[37].enqd()) == 5.0); + wassert(actual_varcode(s[41].code()) == WR_VAR(0, 20, 12)); + wassert(actual(s[41].isset()).isfalse()); + wassert(actual_varcode(s[45].code()) == WR_VAR(0, 20, 12)); + wassert(actual(s[45].isset()).isfalse()); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs1-9.2.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 1); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 9); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 37u); + + wassert(actual_varcode(s[0].code()) == WR_VAR(0, 1, 11)); + wassert(actual(string(s[0].enqc())) == "DFPC"); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs1-11.16.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 1); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 11); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 37u); + + wassert(actual_varcode(s[33].code()) == WR_VAR(0, 10, 197)); + wassert(actual(s[33].enqd()) == 46.0); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs1-13.36.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 1); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 13); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 37u); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs1-19.3.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 1); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 19); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 37u); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/synop-old-buoy.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 1); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 21); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 35u); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs2-101.16.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 2); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 101); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 619u); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs2-102.1.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 2); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 102); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 403u); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs2-91.2.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 2); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 91); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 127u); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/airep-old-4-142.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 4); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 142); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 21u); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs4-144.4.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 4); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 144); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 21u); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs4-145.4.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 4); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 145); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 31u); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/obs3-3.1.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 3); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 3); + wassert(actual(msg.subsets.size()) == 180u); + + wassert(actual(msg.subset(0).size()) == 127u); + wassert(actual(msg.subset(1).size()) == 127u); + wassert(actual(msg.subset(2).size()) == 127u); + wassert(actual(msg.subset(179).size()) == 127u); + }); + + declare_test("bufr/obs3-56.2.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 3); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 56); + wassert(actual(msg.subsets.size()) == 35u); + + wassert(actual(msg.subset(0).size()) == 225u); + wassert(actual(msg.subset(1).size()) == 225u); + wassert(actual(msg.subset(2).size()) == 225u); + wassert(actual(msg.subset(34).size()) == 225u); + }); + + declare_test("bufr/crex-has-few-digits.bufr", [](const BufrBulletin& msg) { + /* + * In this case, the ECMWF table has 12 bits for BUFR in Kelvin (up to 409.6) + * but 3 digits for CREX in Celsius (up to 99.0). This means that BUFR can + * encode values too big to fit in CREX, and when it happens dba_var range + * checks kick in and abort decoding. + */ + }); + + declare_test("bufr/test-buoy1.bufr", [](const BufrBulletin& msg) { + // Buoy who could not look up a D table + }); + + declare_test("bufr/ed4.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 8); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 171); + wassert(actual(msg.subsets.size()) == 128u); + + wassert(actual(msg.subset(0).size()) == 26u); + wassert(actual(msg.subset(1).size()) == 26u); + wassert(actual(msg.subset(2).size()) == 26u); + wassert(actual(msg.subset(127).size()) == 26u); + }); + + declare_test("bufr/ed4date.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 8); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 171); + wassert(actual(msg.subsets.size()) == 128u); + + wassert(actual(msg.rep_year) == 2000); + wassert(actual(msg.rep_month) == 1); + wassert(actual(msg.rep_day) == 2); + wassert(actual(msg.rep_hour) == 7); + wassert(actual(msg.rep_minute) == 0); + wassert(actual(msg.rep_second) == 0); + + wassert(actual(msg.subset(0).size()) == 26u); + wassert(actual(msg.subset(1).size()) == 26u); + wassert(actual(msg.subset(2).size()) == 26u); + wassert(actual(msg.subset(127).size()) == 26u); + }); + + declare_test("bufr/ed2radar.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 2); + wassert(actual(msg.data_category) == 6); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 0); + wassert(actual(msg.subsets.size()) == 1u); + + wassert(actual(msg.rep_year) == 2007); + wassert(actual(msg.rep_month) == 8); + wassert(actual(msg.rep_day) == 13); + wassert(actual(msg.rep_hour) == 18); + wassert(actual(msg.rep_minute) == 30); + wassert(actual(msg.rep_second) == 0); + + wassert(actual(msg.subset(0).size()) == 4606u); + }); + + declare_test("bufr/ed4-compr-string.bufr", [](const BufrBulletin& msg) { + // BUFR4 with compressed strings + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 0); + wassert(actual(msg.data_subcategory) == 2); + wassert(actual(msg.data_subcategory_local) == 0); + wassert(actual(msg.subsets.size()) == 5u); + + wassert(actual(msg.rep_year) == 2009); + wassert(actual(msg.rep_month) == 12); + wassert(actual(msg.rep_day) == 3); + wassert(actual(msg.rep_hour) == 3); + wassert(actual(msg.rep_minute) == 0); + wassert(actual(msg.rep_second) == 0); + + wassert(actual(msg.subset(0).size()) == 115u); + wassert(actual(msg.subset(1).size()) == 115u); + wassert(actual(msg.subset(2).size()) == 115u); + wassert(actual(msg.subset(3).size()) == 115u); + wassert(actual(msg.subset(4).size()) == 115u); + }); + + declare_test("bufr/ed4-parseerror1.bufr", [](const BufrBulletin& msg) { + // BUFR4 which gives a parse error + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 0); + wassert(actual(msg.data_subcategory) == 1); + wassert(actual(msg.data_subcategory_local) == 255); + wassert(actual(msg.subsets.size()) == 5u); + + wassert(actual(msg.rep_year) == 2009); + wassert(actual(msg.rep_month) == 12); + wassert(actual(msg.rep_day) == 3); + wassert(actual(msg.rep_hour) == 3); + wassert(actual(msg.rep_minute) == 0); + wassert(actual(msg.rep_second) == 0); + + wassert(actual(msg.subset(0).size()) == 107u); + wassert(actual(msg.subset(1).size()) == 107u); + wassert(actual(msg.subset(2).size()) == 107u); + wassert(actual(msg.subset(3).size()) == 107u); + wassert(actual(msg.subset(4).size()) == 107u); + }); + + declare_test("bufr/ed4-empty.bufr", [](const BufrBulletin& msg) { + // BUFR4 which does not give a parse error but looks empty + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 0); + wassert(actual(msg.data_subcategory) == 1); + wassert(actual(msg.data_subcategory_local) == 0); + wassert(actual(msg.subsets.size()) == 7u); + + wassert(actual(msg.rep_year) == 2009); + wassert(actual(msg.rep_month) == 12); + wassert(actual(msg.rep_day) == 3); + wassert(actual(msg.rep_hour) == 3); + wassert(actual(msg.rep_minute) == 0); + wassert(actual(msg.rep_second) == 0); + + wassert(actual(msg.subset(0).size()) == 120u); + wassert(actual(msg.subset(1).size()) == 120u); + wassert(actual(msg.subset(2).size()) == 120u); + wassert(actual(msg.subset(3).size()) == 120u); + wassert(actual(msg.subset(4).size()) == 120u); + wassert(actual(msg.subset(5).size()) == 120u); + wassert(actual(msg.subset(6).size()) == 120u); + }); + + declare_test("bufr/C05060.bufr", [](const BufrBulletin& msg) { + // GTS temp message + }); + +#if 0 + declare_test("bufr/tempforecast.bufr", [](const BufrBulletin& msg) { + // Custom ARPA temp forecast message saved as ARPA generic + // TODO: we cannot test this unless we ship dballe's tables + // reenable after deciding whether to ship them or not + }); +#endif + + declare_test("bufr/C23000.bufr", [](const BufrBulletin& msg) { + // C23000 modifier + }); + + declare_test("bufr/segfault1.bufr", [](const BufrBulletin& msg) { + // BUFR that gave segfault + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 2); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 101); + wassert(actual(msg.subsets.size()) == 1u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 129u); + + wassert(actual_varcode(s[9].code()) == WR_VAR(0, 5, 1)); + wassert(actual(s[9].enqd()) == 41.65); + wassert(actual_varcode(s[10].code()) == WR_VAR(0, 6, 1)); + wassert(actual(s[10].enqd()) == 12.43); + + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); + }); + + declare_test("bufr/C08022.bufr", [](const BufrBulletin& msg) { + // C08xxx modifier + }); + + declare_test("bufr/C23000-1.bufr", [](const BufrBulletin& msg) { + // C23xxx modifier on a message that gave problems in some machine + }); + + declare_test("bufr/C08032-toolong.bufr", [](const BufrBulletin& msg) { + }); + + declare_test("bufr/synop-longname.bufr", [](const BufrBulletin& msg) { + // Synop with a very long station name + }); + + declare_test("bufr/C04004.bufr", [](const BufrBulletin& msg) { + // C04yyy modifier, B32021=6 + }); + + declare_test("bufr/C04-B31021-1.bufr", [](const BufrBulletin& msg) { + // C04yyy modifier, B32021=1 + }); + + declare_test("bufr/C06006.bufr", [](const BufrBulletin& msg) { + // C06006 modifier + }); + + declare_test("bufr/gps_zenith.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 0); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 14); + wassert(actual(msg.subsets.size()) == 94u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 175u); + + wassert(actual_varcode(s[0].code()) == WR_VAR(0, 1, 15)); + wassert(actual(s[0].enq()) == "AQUI-BKG_"); + }); + + declare_test("bufr/ascat1.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 12); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 223); + wassert(actual(msg.subsets.size()) == 1722u); + + const Subset& s = msg.subset(0); + wassert(actual(s.size()) == 124u); + + wassert(actual_varcode(s[0].code()) == WR_VAR(0, 1, 33)); + wassert(actual(s[0].enq()) == 254); + }); + + declare_test("bufr/unparsable1.bufr", [](const BufrBulletin& msg) { + }); + + declare_test("bufr/C04type21.bufr", [](const BufrBulletin& msg) { + }); + + declare_test("bufr/noassoc.bufr", [](const BufrBulletin& msg) { + // Buffer with a seemingly missing associated field significance + }); + + declare_test("bufr/atms1.bufr", [](const BufrBulletin& msg) { + // ATMS data (http://npp.gsfc.nasa.gov/atms.html) + }); + + declare_test("bufr/atms2.bufr", [](const BufrBulletin& msg) { + // ATMS data (http://npp.gsfc.nasa.gov/atms.html) + }); + + declare_test("bufr/table17.bufr", [](const BufrBulletin& msg) { + // BUFR data using table 17 + }); + + declare_test("bufr/A_ISMN02LFPW080000RRA_C_RJTD_20140808000319_100.bufr", [](const BufrBulletin& msg) { + }); + + declare_test("bufr/bitmap-B33035.bufr", [](const BufrBulletin& msg) { + }); + + declare_test("bufr/gts-buoy1.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 3); + wassert(actual(msg.data_category) == 1); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 0); + wassert(actual(msg.subsets.size()) == 1u); + }); + + declare_test("bufr/gts-synop-rad1.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 0); + wassert(actual(msg.data_subcategory) == 1); + wassert(actual(msg.data_subcategory_local) == 0); + wassert(actual(msg.subsets.size()) == 25u); + }); + + declare_test("bufr/gts-synop-rad2.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 0); + wassert(actual(msg.data_subcategory) == 6); + wassert(actual(msg.data_subcategory_local) == 150); + wassert(actual(msg.subsets.size()) == 1u); + }); + + declare_test("bufr/gts-synop-tchange.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 0); + wassert(actual(msg.data_subcategory) == 1); + wassert(actual(msg.data_subcategory_local) == 0); + wassert(actual(msg.subsets.size()) == 1u); + }); + + declare_test("bufr/new-003.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 4); + wassert(actual(msg.data_category) == 2); + wassert(actual(msg.data_subcategory) == 10); + wassert(actual(msg.data_subcategory_local) == 1); + wassert(actual(msg.subsets.size()) == 1u); + }); + + declare_test_decode_fail("bufr/afl-src01flip1-pos10.bufr", "but it must be at least 7"); + declare_test_decode_fail("bufr/afl-src4824splice-rep8.bufr", "Optional section length is 3 but it must be at least 4"); + declare_test_decode_fail("bufr/short0.bufr", "looking for section 0 of BUFR message"); + declare_test_decode_fail("bufr/short1.bufr", "looking for section 0 of BUFR message"); + declare_test_decode_fail("bufr/short2.bufr", "Only BUFR edition 2, 3, and 4 are supported"); + declare_test_decode_fail("bufr/short3.bufr", "section 1 (Identification section) claims to end past the end of the BUFR message"); + + declare_test("bufr/issue16-onenull.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 4); + wassert(actual((unsigned)msg.data_category) == 5u); + wassert(actual((unsigned)msg.data_subcategory) == 255u); + wassert(actual((unsigned)msg.data_subcategory_local) == 10u); + wassert(actual(msg.subsets.size()) == 963u); + wassert(actual(msg.subset(0).size()) == 122u); + const Var& pressure = msg.subset(0)[15]; + wassert(actual(pressure.code()) == WR_VAR(0, 7, 4)); + const Var* attr = pressure.enqa(WR_VAR(0, 33, 7)); + wassert_true(attr); + wassert(actual(attr->enqi()) == 84); + }); + + declare_test("bufr/issue16-twonull.bufr", [](const BufrBulletin& msg) { + wassert(actual(msg.edition_number) == 4); + wassert(actual((unsigned)msg.data_category) == 5u); + wassert(actual((unsigned)msg.data_subcategory) == 255u); + wassert(actual((unsigned)msg.data_subcategory_local) == 10u); + wassert(actual(msg.subsets.size()) == 963u); + wassert(actual(msg.subset(0).size()) == 122u); + const Var& pressure = msg.subset(0)[15]; + wassert(actual(pressure.code()) == WR_VAR(0, 7, 4)); + const Var* attr = pressure.enqa(WR_VAR(0, 33, 7)); + wassert_true(attr); + wassert(actual(attr->enqi()) == 87); + }); + } +} testnewtg("bufr_decoder"); + + +#if 0 +template<> template<> +void to::test<3>() +{ +#if 0 + *** Disabled because this test data uses a template that we do not support + + TestBufrexRaw test; + test.setEdition(3); + test.setCat(1); + test.setSubcat(12); + test.setVars(119); + test.set(WR_VAR(0, 5, 2), 54.10); + test.set(WR_VAR(0, 6, 2), 12.10); + + bufrex_msg msg = read_test_msg_raw("bufr/bufr3", BUFR); + ensureBufrexRawEquals(test, msg); + + bufrex_msg msg1 = reencode_test(msg, BUFR); + ensureBufrexRawEquals(test, msg1); + + bufrex_msg_delete(msg); + bufrex_msg_delete(msg1); +#endif +} + +// Soil temperature message +template<> template<> +void to::test<24>() +{ +#if 0 + // TODO: this seems to be a problem in the input message. + // we can disregard it until someone proves it's our problem and not + // the problem of who generated the message + + /* + TestBufrexMsg test; + test.edition = 2; + test.cat = 6; + test.subcat = 255; + test.localsubcat = 0; + test.subsets = 1; + */ + + //bufrex_msg msg = read_test_msg_header_raw("bufr/test-soil1.bufr", BUFR); + /* + ensureBufrexRawEquals(test, msg); + wassert(actual(msg->rep_year) == 2007); + wassert(actual(msg->rep_month) == 8); + wassert(actual(msg->rep_day) == 13); + wassert(actual(msg->rep_hour) == 18); + wassert(actual(msg->rep_minute) == 30); + wassert(actual(msg->rep_second) == 0); + + test.subset(0).vars = 4606; + */ + + //bufrex_msg msg1 = reencode_test(msg); + //ensureBufrexRawEquals(test, msg1); + + struct Tester : public MsgTester { + void test(const BufrBulletin& msg) + { + /* + wassert(actual(msg.edition_number) == 2); + wassert(actual(msg.data_category) == 6); + wassert(actual(msg.data_subcategory) == 255); + wassert(actual(msg.data_subcategory_local) == 0); + wassert(actual(msg.subsets.size()) == 1u); + + wassert(actual(msg.rep_year) == 2007); + wassert(actual(msg.rep_month) == 8); + wassert(actual(msg.rep_day) == 13); + wassert(actual(msg.rep_hour) == 18); + wassert(actual(msg.rep_minute) == 30); + wassert(actual(msg.rep_second) == 0); + + wassert(actual(msg.subset(0).size()) == 4606u); + + const Subset& s = msg.subset(0); + + // FIXME Does it have this? + wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[0].enqa(WR_VAR(0) == 33, 7))->enqi(), 70); + + wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); + wassert(actual(s[5].enqa(WR_VAR(0) == 33, 7))->enqi(), 70); + */ + } + } test; + + // FIXME: recoding might not work + declare_test("bufr/test-soil1.bufr", [](const BufrBulletin& msg) +#endif +} + +#endif + +} diff -Nru wreport-3.6/wreport/bufr/input.cc wreport-3.15/wreport/bufr/input.cc --- wreport-3.6/wreport/bufr/input.cc 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/bufr/input.cc 2018-07-26 09:28:33.000000000 +0000 @@ -0,0 +1,700 @@ +#include "input.h" +#include "trace.h" +#include "wreport/bulletin/associated_fields.h" +#include + +namespace { +const char* bufr_sec_names[] = { + "Indicator section", + "Identification section", + "Optional section", + "Data desription section", + "Data section", + "End section" +}; + +// Return a value with bitlen bits set to 1 +static inline uint32_t all_ones(int bitlen) +{ + return ((1 << (bitlen - 1))-1) | (1 << (bitlen - 1)); +} +} + +namespace wreport { +namespace bufr { + +Input::Input(const std::string& in) +{ + data = (const unsigned char*)in.data(); + data_len = in.size(); + for (auto& s: sec) + s = 0; +} + +void Input::scan_section_length(unsigned sec_no) +{ + if (sec[sec_no] + 3 > data_len) + parse_error(sec[sec_no], "section %d (%s) is too short to hold the section size indicator", + sec_no, bufr_sec_names[sec_no]); + + sec[sec_no + 1] = sec[sec_no] + read_number(sec_no, 0, 3); + + if (sec[sec_no + 1] > data_len) + parse_error(sec[sec_no], "section %d (%s) claims to end past the end of the BUFR message", + sec_no, bufr_sec_names[sec_no]); +} + +void Input::scan_lead_sections() +{ + sec[1] = sec[0] + 8; + scan_section_length(1); +} + +void Input::scan_other_sections(bool has_optional) +{ + if (has_optional) + { + scan_section_length(2); + } else + sec[3] = sec[2]; + + for (unsigned i = 3; i < 5; ++i) + scan_section_length(i); + + s4_cursor = sec[4] + 4; +} + +void Input::debug_dump_next_bits(const char* desc, int count) const +{ + fputs(desc, stderr); + size_t cursor = s4_cursor; + int pbyte = this->pbyte; + int pbyte_len = this->pbyte_len; + int i; + + for (i = 0; i < count; ++i) + { + if (cursor == data_len) + break; + if (pbyte_len == 0) + { + pbyte_len = 8; + pbyte = data[cursor++]; + putc(' ', stderr); + } + putc((pbyte & 0x80) ? '1' : '0', stderr); + pbyte <<= 1; + --pbyte_len; + } + putc('\n', stderr); +} + +void Input::parse_error(const char* fmt, ...) const +{ + char* context; + char* message; + + va_list ap; + va_start(ap, fmt); + if (vasprintf(&message, fmt, ap) == -1) + message = nullptr; + va_end(ap); + + if (asprintf(&context, "%s:%zd+%u: %s", fname, start_offset, s4_cursor, message ? message : fmt) == -1) + context = nullptr; + free(message); + + std::string msg(context ? context : fmt); + free(context); + + throw error_parse(msg); +} + +void Input::parse_error(unsigned pos, const char* fmt, ...) const +{ + char* context; + char* message; + + va_list ap; + va_start(ap, fmt); + if (vasprintf(&message, fmt, ap) == -1) + message = nullptr; + va_end(ap); + + if (asprintf(&context, "%s:%zd+%u: %s", fname, start_offset, pos, message ? message : fmt) == -1) + context = nullptr; + free(message); + + std::string msg(context ? context : fmt); + free(context); + throw error_parse(msg); +} + +void Input::parse_error(unsigned section, unsigned pos, const char* fmt, ...) const +{ + char* context; + char* message; + + va_list ap; + va_start(ap, fmt); + if (vasprintf(&message, fmt, ap) == -1) + message = nullptr; + va_end(ap); + + if (asprintf(&context, "%s:%zd+%u: %s (%db inside section %s)", + fname, start_offset, sec[section] + pos, message ? message : fmt, + pos, bufr_sec_names[section]) == -1) + context = nullptr; + free(message); + + std::string msg(context ? context : fmt); + free(context); + throw error_parse(msg); +} + +void Input::check_available_data(unsigned pos, size_t datalen, const char* expected) +{ + if (pos + datalen > data_len) + parse_error(pos, "end of BUFR message while looking for %s", expected); +} + +void Input::check_available_message_data(unsigned section, unsigned pos, size_t datalen, const char* expected) +{ + if (sec[section] + pos + datalen > data_len) + parse_error(section, pos, "end of BUFR message while looking for %s", expected); +} + +void Input::check_available_section_data(unsigned section, unsigned pos, size_t datalen, const char* expected) +{ + if (section < 5) + { + if (sec[section] + pos + datalen > sec[section + 1]) + parse_error(section, pos, "end of BUFR section while looking for %s", expected); + } else { + if (sec[section] + pos + datalen > data_len) + parse_error(section, pos, "end of BUFR message while looking for %s", expected); + } +} + +bool Input::decode_string(unsigned bit_len, char* str, size_t& len) +{ + int toread = bit_len; + bool missing = true; + len = 0; + + while (toread > 0) + { + int count = toread > 8 ? 8 : toread; + uint32_t bitval = get_bits(count); + /* Check that the string is not all 0xff, meaning missing value */ + if (bitval != 0xff && bitval != 0) + missing = false; + str[len++] = bitval; + toread -= count; + } + + if (!missing) + { + str[len] = 0; + + /* Convert space-padding into zero-padding */ + for (; len > 1 && (str[len - 1] == 0 || isspace(str[len - 1])); + --len) + str[len - 1] = 0; + } + + return !missing; +} + +void Input::decode_string(Var& dest) +{ + Varinfo info = dest.info(); + + char str[info->bit_len / 8 + 2]; + size_t len; + bool missing = !decode_string(info->bit_len, str, len); + + /* Store the variable that we found */ + // Set the variable value + if (!missing) + dest.setc(str); +} + +void Input::decode_binary(Var& dest) +{ + Varinfo info = dest.info(); + + unsigned char buf[info->bit_len / 8 + 1]; + size_t len = 0; + unsigned toread = info->bit_len; + bool missing = true; + + while (toread > 0) + { + unsigned count = toread > 8 ? 8 : toread; + uint32_t bitval = get_bits(count); + /* Check that the string is not all 0xff, meaning missing value */ + if (bitval != 0xff) + missing = false; + buf[len++] = bitval; + toread -= count; + } + + /* Store the variable that we found */ + // Set the variable value + if (!missing) + dest.setc((char*)buf); +} + +void Input::decode_number(Var& dest) +{ + Varinfo info = dest.info(); + + uint32_t val = get_bits(info->bit_len); + + // TRACE("datasec:decode_b_num:reading %s (%s), size %d, scale %d, starting point %d\n", info->desc, info->bufr_unit, info->bit_len, info->scale, val); + + // Check if there are bits which are not 1 (that is, if the value is present) + // In case of delayed replications, there is no missing value + bool missing = false; + if (WR_VAR_X(info->code) == 31 && WR_VAR_F(info->code) == 0) + switch (WR_VAR_Y(info->code)) + { + case 0: + case 1: + case 2: + case 11: + case 12: + break; + default: + missing = (val == all_ones(info->bit_len)); + } + else + missing = (val == all_ones(info->bit_len)); + + // TRACE("datasec:decode_b_num:len %d val %d info-len %d info-desc %s\n", info->bit_len, val, info->bit_len, info->desc); + + /* Store the variable that we found */ + if (missing) + { + /* Create the new Var */ + // TRACE("datasec:decode_b_num:decoded as missing\n"); + dest.unset(); + } else { + double dval = info->decode_binary(val); + // TRACE("datasec:decode_b_num:decoded as %f %s\n", dval, info->bufr_unit); + /* Create the new Var */ + dest.setd(dval); + } +} + +bool Input::decode_compressed_base(Varinfo info, uint32_t& base, uint32_t& diffbits) +{ + // Data field base value + base = get_bits(info->bit_len); + + // Check if there are bits which are not 1 (that is, if the value is present) + bool missing = (base == all_ones(info->bit_len)); + + // We just decoded the base value. Now we need to decode all the offsets + + // Decode the number of bits (encoded in 6 bits) that these difference + // values occupy + diffbits = get_bits(6); + if (missing && diffbits != 0) + error_consistency::throwf("When decoding compressed BUFR data, the difference bit length must be 0 (and not %d like in this case) when the base value is missing", diffbits); + + return missing; +} + +void Input::decode_compressed_number(Var& dest, uint32_t base, unsigned diffbits) +{ + Varinfo info = dest.info(); + + // Decode the difference value + uint32_t diff = get_bits(diffbits); + + // Check if it's all 1s: in that case it's a missing value + if (base == all_ones(info->bit_len) || diff == all_ones(diffbits)) + { + /* Missing value */ + //TRACE("datasec:decode_b_num:decoded[%d] as missing\n", i); + dest.unset(); + } else { + // Compute the value for this subset + uint32_t newval = base + diff; + double dval = info->decode_binary(newval); + TRACE("Input:decode_number:decoded diffbits %u %u+%u=%u->%f %01d%02d%03d %s\n", + diffbits, base, diff, newval, dval, WR_VAR_FXY(info->code), info->unit); + + /* Create the new Var */ + dest.setd(dval); + } +} + +void Input::decode_compressed_number(Varinfo info, const bulletin::AssociatedField& associated_field, unsigned subsets, std::function dest) +{ + Var var(info); + + // debug_dump_next_bits("DECODE NUMBER: ", 30); + + /* I could not find any specification describing the behaviour of associated fields in compressed BUFRs. + * + * By empirical observation, I assume this behaviour: + * + * - $ASSOCIATED_FIELD_BITS bits of base value for the associated field + * - 6 bits specifying the number of bits used to encode the associated + * field difference values + * - base value for the actual variable (number of bits defined in table B) + * - 6 difference bits for the actual variable + * + * Then, for each subset: + * - the difference bits for the associated field + * - the difference bits for the actual variable + */ + + /// Associated field base value + uint32_t af_base = get_bits(associated_field.bit_count); + /// Number of bits used to encode the associated field differences + uint32_t af_diffbits = get_bits(6); + + // Data field base value + uint32_t base = get_bits(info->bit_len); + + //TRACE("datasec:decode_b_num:reading %s (%s), size %d, scale %d, starting point %d\n", info->desc, info->bufr_unit, info->bit_len, info->scale, base); + + /* Check if there are bits which are not 1 (that is, if the value is present) */ + bool missing = (base == all_ones(info->bit_len)); + + /*bufr_decoder_debug(decoder, " %s: %d%s\n", info.desc, base, info.type);*/ + //TRACE("datasec:decode_b_num:len %d base %d info-len %d info-desc %s\n", info->bit_len, base, info->bit_len, info->desc); + + /* Store the variable that we found */ + + /* If compression is in use, then we just decoded the base value. Now + * we need to decode all the offsets */ + + /* Decode the number of bits (encoded in 6 bits) that these difference + * values occupy */ + uint32_t diffbits = get_bits(6); + if (missing && diffbits != 0) + error_consistency::throwf("When decoding compressed BUFR data, the difference bit length must be 0 (and not %d like in this case) when the base value is missing", diffbits); + + //TRACE("Compressed number, base value %d diff bits %d\n", base, diffbits); + + for (unsigned i = 0; i < subsets; ++i) + { + uint32_t af_value = af_base + get_bits(af_diffbits); + decode_compressed_number(var, base, diffbits); + std::unique_ptr af(associated_field.make_attribute(af_value)); + if (af.get()) var.seta(std::move(af)); + dest(i, std::move(var)); + } +} + +void Input::decode_compressed_semantic_number(Var& dest, unsigned subsets) +{ + Varinfo info = dest.info(); + + uint32_t base = get_bits(info->bit_len); + + //TRACE("datasec:decode_b_num:reading %s (%s), size %d, scale %d, starting point %d\n", info->desc, info->bufr_unit, info->bit_len, info->scale, base); + + // Check if there are bits which are not 1 (that is, if the value is present) + bool missing = (base == all_ones(info->bit_len)); + + //TRACE("datasec:decode_b_num:len %d base %d info-len %d info-desc %s\n", info->bit_len, base, info->bit_len, info->desc); + + // Store the variable that we found + + /* If compression is in use, then we just decoded the base value. Now we + * need to decode all the offsets. However, since this value cannot change + * across subsets without breaking the alignment of the variables in the + * various subsets, we only need to check that the 6-bits difference value + * size is 0, and use the base value we just decoded as the final value */ + uint32_t diffbits = get_bits(6); + if (diffbits) + error_consistency::throwf("cannot handle a semantic variable (like a repetition count) that differs across subsets"); + + //TRACE("Compressed number, base value %d diff bits %d\n", base, diffbits); + + // Decode the destination variable + if (missing) + { + //TRACE("datasec:decode_b_num:decoded[%d] as missing\n", i); + dest.unset(); + } else { + double dval = info->decode_binary(base); + dest.setd(dval); + } +} + +void Input::decode_string(Varinfo info, unsigned subsets, std::function dest) +{ + char str[info->bit_len / 8 + 2]; + size_t len; + bool missing = !decode_string(info->bit_len, str, len); + + /* Store the variable that we found */ + + /* If compression is in use, then we just decoded the base value. Now + * we need to decode all the offsets */ + + /* Decode the number of bits (encoded in 6 bits) that these difference + * values occupy */ + uint32_t diffbits = get_bits(6); + + //TRACE("datadesc:decode_b_string:compressed string, base:%.*s, diff bits %d\n", (int)len, str, diffbits); + + if (diffbits != 0) + { + Var var(info); + + /* For compressed strings, the reference value must be all zeros */ + for (size_t i = 0; i < len; ++i) + if (str[i] != 0) + error_unimplemented::throwf("compressed strings with %d bit deltas have non-zero reference value", diffbits); + + /* Let's also check that the number of + * difference characters is the same length as + * the reference string */ + if (diffbits > len) + error_unimplemented::throwf("compressed strings with %zd characters have %d bit deltas (deltas should not be longer than field)", len, diffbits); + + for (unsigned i = 0; i < subsets; ++i) + { + // Set the variable value + if (decode_string(diffbits * 8, str, len)) + { + /* Compute the value for this subset */ + //TRACE("datadesc:decode_b_string:decoded[%d] as \"%s\"\n", i, str); + var.setc(str); + } else { + /* Missing value */ + //TRACE("datadesc:decode_b_string:decoded[%d] as missing\n", i); + var.unset(); + } + + // Add it to this subset + dest(i, std::move(var)); + } + } else { + Var var(info); + if (!missing) var.setc(str); + + // Add the string to all the subsets + for (unsigned i = 0; i < subsets; ++i) + dest(i, Var(var)); + } +} + +void Input::decode_string(Var& dest, unsigned subsets) +{ + Varinfo info = dest.info(); + + char str[info->bit_len / 8 + 2]; + size_t len; + bool missing = !decode_string(info->bit_len, str, len); + + /* Store the variable that we found */ + + /* If compression is in use, then we just decoded the base value. Now + * we need to decode all the offsets */ + + /* Decode the number of bits (encoded in 6 bits) that these difference + * values occupy */ + uint32_t diffbits = get_bits(6); + + //TRACE("datadesc:decode_b_string:compressed string, base:%.*s, diff bits %d\n", (int)len, str, diffbits); + + if (diffbits == 0) + { + if (!missing) + dest.setc(str); + } else { + /* For compressed strings, the reference value must be all zeros */ + for (size_t i = 0; i < len; ++i) + if (str[i] != 0) + error_unimplemented::throwf("compressed strings with %d bit deltas have non-zero reference value", diffbits); + + /* Let's also check that the number of + * difference characters is the same length as + * the reference string */ + if (diffbits > len) + error_unimplemented::throwf("compressed strings with %zd characters have %d bit deltas (deltas should not be longer than field)", len, diffbits); + + // Set the variable value + if (decode_string(diffbits * 8, str, len)) + { + /* Compute the value for this subset */ + //TRACE("datadesc:decode_b_string:decoded[%d] as \"%s\"\n", i, str); + dest.setc(str); + } else { + /* Missing value */ + //TRACE("datadesc:decode_b_string:decoded[%d] as missing\n", i); + dest.unset(); + } + + Var copy(dest.info()); + for (unsigned i = 1; i < subsets; ++i) + { + // TODO: only compare the diffbits without needing to reconstruct the var + + // Set the variable value + if (decode_string(diffbits * 8, str, len)) + { + /* Compute the value for this subset */ + //TRACE("datadesc:decode_b_string:decoded[%d] as \"%s\"\n", i, str); + copy.setc(str); + } else { + /* Missing value */ + //TRACE("datadesc:decode_b_string:decoded[%d] as missing\n", i); + copy.unset(); + } + + if (dest != copy) + { + std::string val1 = dest.format(); + std::string val2 = copy.format(); + error_consistency::throwf("When decoding %d%02d%03d from compressed BUFR data, decoded values differ (%s != %s) but should all be the same", + WR_VAR_F(dest.code()), WR_VAR_X(dest.code()), WR_VAR_Y(dest.code()), + val2.c_str(), val1.c_str()); + } + } + } +} + +void Input::decode_compressed_number(Varinfo info, unsigned subsets, std::function dest) +{ + // Data field base value + uint32_t base; + + // Number of bits used for each difference value + uint32_t diffbits; + + bool missing = decode_compressed_base(info, base, diffbits); + if (missing) + { + for (unsigned i = 0; i < subsets; ++i) + dest(i, Var(info)); + } + else if (!diffbits) + { + Var var(info, info->decode_binary(base)); + for (unsigned i = 0; i < subsets; ++i) + dest(i, Var(var)); + } + else + { + Var var(info); + for (unsigned i = 0; i < subsets; ++i) + { + decode_compressed_number(var, base, diffbits); + dest(i, std::move(var)); + } + } +} + +void Input::decode_string(Varinfo info, unsigned subsets, DispatchToSubsets& dest) +{ + // Decode the base value + char str[info->bit_len / 8 + 2]; + size_t len; + bool missing = !decode_string(info->bit_len, str, len); + + // Decode the number of bits (encoded in 6 bits) for each difference + // value + uint32_t diffbits = get_bits(6); + + if (missing && diffbits == 0) + dest.add_missing(info); + else if (diffbits == 0) + { + // Add the same string to all the subsets + dest.add_same(Var(info, str)); + } else { + /* For compressed strings, the reference value must be all zeros */ + for (size_t i = 0; i < len; ++i) + if (str[i] != 0) + error_unimplemented::throwf("compressed strings with %d bit deltas have non-zero reference value", diffbits); + + /* Let's also check that the number of + * difference characters is the same length as + * the reference string */ + if (diffbits > len) + error_unimplemented::throwf("compressed strings with %zd characters have %d bit deltas (deltas should not be longer than field)", len, diffbits); + + for (unsigned i = 0; i < subsets; ++i) + { + // Set the variable value + if (decode_string(diffbits * 8, str, len)) + { + // Compute the value for this subset + dest.add_var(i, Var(info, str)); + } else { + // Missing value + dest.add_var(i, Var(info)); + } + } + } +} + +void Input::decode_compressed_number(Varinfo info, unsigned subsets, DispatchToSubsets& dest) +{ + // Data field base value + uint32_t base; + + // Number of bits used for each difference value + uint32_t diffbits; + + bool missing = decode_compressed_base(info, base, diffbits); + if (missing) + dest.add_missing(info); + else if (!diffbits) + dest.add_same(Var(info, info->decode_binary(base))); + else + { + Var var(info); + for (unsigned i = 0; i < subsets; ++i) + { + decode_compressed_number(var, base, diffbits); + dest.add_var(i, std::move(var)); + } + } +} + +std::string Input::decode_uncompressed_bitmap(unsigned size) +{ + std::string buf; + buf.resize(size); + for (unsigned i = 0; i < size; ++i) + { + uint32_t val = get_bits(1); + buf[i] = (val == 0) ? '+' : '-'; + } + return buf; +} + +std::string Input::decode_compressed_bitmap(unsigned size) +{ + std::string buf; + buf.resize(size); + for (unsigned i = 0; i < size; ++i) + { + uint32_t val = get_bits(1); + buf[i] = (val == 0) ? '+' : '-'; + // Decode the number of bits (encoded in 6 bits) of difference + // values. It's odd to repeat this for each bit in the bitmap, but + // that's how things are transmitted and it's somewhat consistent + // with how data compression is specified + val = get_bits(6); + // If compressed, ensure that the difference bits are 0 and they are + // not trying to transmit odd things like delta bitmaps + if (val != 0) + parse_error("bitmap entry %u declares %u difference bits, but we only support 0", i, val); + } + return buf; +} + +} +} diff -Nru wreport-3.6/wreport/bufr/input.h wreport-3.15/wreport/bufr/input.h --- wreport-3.6/wreport/bufr/input.h 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/bufr/input.h 2018-07-26 09:27:53.000000000 +0000 @@ -0,0 +1,396 @@ +#ifndef WREPORT_BUFR_INPUT_H +#define WREPORT_BUFR_INPUT_H + +#include +#include +#include +#include +#include + +namespace wreport { +struct Bulletin; + +namespace bulletin { +struct AssociatedField; +} + +namespace bufr { + +struct DispatchToSubsets +{ + Bulletin& out; + unsigned subset_count; + DispatchToSubsets(Bulletin& out, unsigned subset_count) : out(out), subset_count(subset_count) {} + + void add_missing(Varinfo info) + { + for (unsigned i = 0; i < subset_count; ++i) + out.subsets[i].store_variable_undef(info); + } + void add_same(const Var& var) + { + for (unsigned i = 0; i < subset_count; ++i) + out.subsets[i].store_variable(Var(var)); + } + void add_var(unsigned subset, Var&& var) + { + out.subsets[subset].store_variable(var); + } +}; + + +/** + * Binary buffer with bit-level read operations + */ +class Input +{ +protected: + /** + * Scan length of section \a sec_no, filling in the start of the next + * section in sec[sec_no + 1] + */ + void scan_section_length(unsigned sec_no); + +public: + /// Input buffer + const uint8_t* data; + + /// Input buffer size + size_t data_len; + + /** + * Input file name (optional). + * + * If available, it will be used to generate better error messages. + * + * If not available, it is NULL. + */ + const char* fname = nullptr; + + /** + * File offset of the start of the message. + * + * If available, it will be used to generate better error messages. + * + * If not available, it is 0. + */ + size_t start_offset = 0; + + /// Offset of the byte we are currently decoding + unsigned s4_cursor = 0; + + /// Byte we are currently decoding + uint8_t pbyte = 0; + + /// Bits left in pbyte to decode + int pbyte_len = 0; + + /// Offsets of the start of BUFR sections + unsigned sec[6]; + + + /** + * Wrap a string iinto a Input + * + * @param in + * String with the data to read + */ + Input(const std::string& in); + + /** + * Scan the message filling in the sec[] array of start offsets of sections + * 0 and 1. + * + * We cannot scan past section 1 until we decode it, because we need to + * know if section 2 is present or not + */ + void scan_lead_sections(); + + /** + * Scan the message filling in the sec[] array of section start offsets of + * all sections from 2 on. + * + * It also initialises points s4_cursor to the begin of the data in section + * 4. + * + * @param has_optional + * True if the optional section is present, false if it should be + * skipped. + */ + void scan_other_sections(bool has_optional); + + /// Return the current decoding byte offset + unsigned offset() const { return s4_cursor; } + + /// Return the number of bits left in the message to be decoded + unsigned bits_left() const { return (data_len - s4_cursor) * 8 + pbyte_len; } + + /// Read a byte value at offset \a pos + inline unsigned read_byte(unsigned pos) const + { + return (unsigned)data[pos]; + } + + /// Read a byte value at offset \a pos inside section \a section + inline unsigned read_byte(unsigned section, unsigned pos) const + { + return (unsigned)data[sec[section] + pos]; + } + + /// Read a big endian integer value \a byte_len bytes long, at offset \a pos + unsigned read_number(unsigned pos, unsigned byte_len) const + { + unsigned res = 0; + for (unsigned i = 0; i < byte_len; ++i) + { + res <<= 8; + res |= data[pos + i]; + } + return res; + } + + /** + * Read a big endian integer value \a byte_len bytes long, at offset \a pos + * inside section \a section + */ + inline unsigned read_number(unsigned section, unsigned pos, unsigned byte_len) const + { + return read_number(sec[section] + pos, byte_len); + } + + /** + * Get the integer value of the next 'n' bits from the decode input + * n must be <= 32. + */ + uint32_t get_bits(unsigned n) + { + uint32_t result = 0; + + if (s4_cursor == data_len) + parse_error("end of buffer while looking for %d bits of bit-packed data", n); + + // TODO: review and benchmark and possibly simplify + // (a possible alternative approach is to keep a current bitmask that + // starts at 0x80 and is shifted right by 1 at each read until it + // reaches 0, and get rid of pbyte_len) + for (unsigned i = 0; i < n; i++) + { + if (pbyte_len == 0) + { + pbyte_len = 8; + pbyte = data[s4_cursor++]; + } + result <<= 1; + if (pbyte & 0x80) + result |= 1; + pbyte <<= 1; + pbyte_len--; + } + + return result; + } + + /// Dump to stderr 'count' bits of 'buf', starting at the 'ofs-th' bit + void debug_dump_next_bits(const char* desc, int count) const; + + /// Throw an error_parse at the current decoding location + void parse_error(const char* fmt, ...) const WREPORT_THROWF_ATTRS(2, 3); + + /// Throw an error_parse at the given decoding location + void parse_error(unsigned pos, const char* fmt, ...) const WREPORT_THROWF_ATTRS(3, 4); + + /// Throw an error_parse at the given decoding location inside the given section + void parse_error(unsigned section, unsigned pos, const char* fmt, ...) const WREPORT_THROWF_ATTRS(4, 5); + + /** + * Check that the input buffer contains at least \a datalen characters + * after offset \a pos; throw error_parse otherwise. + * + * @param pos + * Starting offset of the required data + * @param datalen + * Required amount of data expected starting from \a pos + * @param expected + * name of what we are about to decode, used for generating nice error + * messages + */ + void check_available_data(unsigned pos, size_t datalen, const char* expected); + + /** + * Check that the input buffer contains at least \a datalen characters + * after offset \a pos in section \a section; throw error_parse otherwise. + * + * @param section + * Number of the section to check + * @param pos + * Starting offset inside the section of the required data + * @param datalen + * Required amount of data expected starting from \a pos + * @param expected + * Name of what we are about to decode, used for generating nice error + * messages + */ + void check_available_message_data(unsigned section, unsigned pos, size_t datalen, const char* expected); + + /** + * Check that the given section in the input buffer contains at least \a + * datalen characters after offset \a pos; throw error_parse otherwise. + * + * @param section + * Number of the section to check + * @param pos + * Starting offset inside the section of the required data + * @param datalen + * Required amount of data expected starting from \a pos + * @param expected + * Name of what we are about to decode, used for generating nice error + * messages + */ + void check_available_section_data(unsigned section, unsigned pos, size_t datalen, const char* expected); + + /** + * Decode a compressed number as described by dest.info(), ad set it as + * value for \a dest. + * + * @param dest + * Variable which holds the decoding information and that will hold the + * decoded value + * @param base + * The base value for the compressed number + * @param diffbits + * The number of bits used to encode the difference from \a base + */ + void decode_compressed_number(Var& dest, uint32_t base, unsigned diffbits); + + /** + * Decode a number as described by dest.info(), and set it as value for \a + * dest. + * + * @param dest + * Variable which holds the decoding information and that will hold the + * decoded value + */ + void decode_number(Var& dest); + + bool decode_compressed_base(Varinfo info, uint32_t& base, uint32_t& diffbits); + + /** + * Decode a number as described by \a info from a compressed bufr with + * \a subsets subsets, and send the resulting variables to \a dest + */ + void decode_compressed_number(Varinfo info, unsigned subsets, std::function dest); + + void decode_string(Varinfo info, unsigned subsets, DispatchToSubsets& dest); + + void decode_compressed_number(Varinfo info, unsigned subsets, DispatchToSubsets& dest); + + /** + * Decode a number as described by \a info from a compressed bufr with + * \a subsets subsets, and send the resulting variables to \a dest + */ + void decode_compressed_number(Varinfo info, const bulletin::AssociatedField& afield, unsigned subsets, std::function dest); + + /** + * Decode a number as described by dest.info(), and set it as value for \a + * dest. The number is decoded for \a subsets compressed datasets, and an + * exception is thrown if the values differ. + * + * @param dest + * Variable which holds the decoding information and that will hold the + * decoded value + * @param subsets + * Number of subsets in the compressed data section + */ + void decode_compressed_semantic_number(Var& dest, unsigned subsets); + + /** + * Read a string from the data section + * + * @param bit_len + * Number of bits (not bytes) to read. It is normally a multiple of 8, + * and when it is not, the last character will contain the partial byte + * read. + * @retval str + * Buffer where the string is written. Must be big enough to contain the + * longest string described by info, plus 2 bytes + * @retval len + * The string length + * @return + * true if we decoded a real string, false if we decoded a missing string + * value + */ + bool decode_string(unsigned bit_len, char* str, size_t& len); + + /** + * Decode a string as described by dest.info(), ad set it as value for \a + * dest. + * + * It is assumed that \a dest is not set, therefore in case we decode a + * missing value, \a dest will not be touched. + * + * @param dest + * Variable which holds the decoding information and that will hold the + * decoded value + */ + void decode_string(Var& dest); + + /** + * Decode a string as described by dest.info(), and set it as value for \a + * dest. The string is decoded for \a subsets compressed datasets, and an + * exception is thrown if the values differ. + * + * @param dest + * Variable which holds the decoding information and that will hold the + * decoded value + * @param subsets + * Number of subsets in the compressed data section + */ + void decode_string(Var& dest, unsigned subsets); + + /** + * Decode a string as described by \a info from a compressed bufr with \a + * subsets subsets, and send the resulting variables to \a dest + */ + void decode_string(Varinfo info, unsigned subsets, std::function dest); + + /** + * Decode a generic binary value as-is, as described by dest.info(), ad set + * it as value for \a dest. + * + * It is assumed that \a dest is not set, therefore in case we decode a + * missing value, \a dest will not be touched. + * + * @param dest + * Variable which holds the decoding information and that will hold the + * decoded value + */ + void decode_binary(Var& dest); + + /** + * Decode an uncompressed bitmap of \a size bits. + * + * The result will be a string \a size bytes long, with a '+' where the + * bitmap reports that data is present, and a '-' where the bitmap reports + * that data is not present. + */ + std::string decode_uncompressed_bitmap(unsigned size); + + /** + * Decode a "compressed" bitmap of \a size bits. + * + * The result will be a string \a size bytes long, with a '+' where the + * bitmap reports that data is present, and a '-' where the bitmap reports + * that data is not present. + * + * It would be more correct to say that it decodes a bitmap from a + * compressed BUFR message, because bitmaps in compressed messages are + * actually encoded with 7 bits per bit instead of one, because after each + * bit they need to send 6 bits saying that it will be followed by 0 bits + * of difference values. + */ + std::string decode_compressed_bitmap(unsigned size); +}; + +} +} +#endif diff -Nru wreport-3.6/wreport/bufr/input-test.cc wreport-3.15/wreport/bufr/input-test.cc --- wreport-3.6/wreport/bufr/input-test.cc 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/bufr/input-test.cc 2018-05-14 15:34:17.000000000 +0000 @@ -0,0 +1,22 @@ +#include "wreport/tests.h" +#include "input.h" + +using namespace wreport; +using namespace wreport::tests; +using namespace std; + +namespace { + +class Tests : public TestCase +{ + using TestCase::TestCase; + + void register_tests() override + { + add_method("empty", []() { + }); + } +} test("bufr_input"); + +} + diff -Nru wreport-3.6/wreport/bufr/trace.h wreport-3.15/wreport/bufr/trace.h --- wreport-3.6/wreport/bufr/trace.h 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/bufr/trace.h 2018-05-14 15:34:17.000000000 +0000 @@ -0,0 +1,14 @@ +#ifndef WREPORT_BUFR_TRACE_H +#define WREPORT_BUFR_TRACE_H + +//#define TRACE_DECODER + +#ifdef TRACE_DECODER +#define TRACE(...) fprintf(stderr, __VA_ARGS__) +#define IFTRACE if (1) +#else +#define TRACE(...) do { } while (0) +#define IFTRACE if (0) +#endif + +#endif diff -Nru wreport-3.6/wreport/bufr_decoder.cc wreport-3.15/wreport/bufr_decoder.cc --- wreport-3.6/wreport/bufr_decoder.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bufr_decoder.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,665 +0,0 @@ -#include "bulletin.h" -#include "bulletin/internals.h" -#include "buffers/bufr.h" -#include -#include "config.h" - -// #define TRACE_DECODER - -#ifdef TRACE_DECODER -#define TRACE(...) fprintf(stderr, __VA_ARGS__) -#define IFTRACE if (1) -#else -#define TRACE(...) do { } while (0) -#define IFTRACE if (0) -#endif - -using namespace std; - -namespace wreport { -namespace { - -// Return a value with bitlen bits set to 1 -static inline uint32_t all_ones(int bitlen) -{ - return ((1 << (bitlen - 1))-1) | (1 << (bitlen - 1)); -} - -struct Decoder -{ - /// Input data - buffers::BufrInput in; - /* Output decoded variables */ - BufrBulletin& out; - /// Number of expected subsets (read in decode_header, used in decode_data) - size_t expected_subsets; - /// True if undefined attributes are added to the output, else false - bool conf_add_undef_attrs = false; - /// Optional section length decoded from the message - unsigned optional_section_length = 0; - - Decoder(const std::string& buf, const char* fname, size_t offset, BufrBulletin& out) - : in(buf), out(out) - { - in.fname = fname; - in.start_offset = offset; - } - - void read_options(const BufrCodecOptions& opts) - { - conf_add_undef_attrs = opts.decode_adds_undef_attrs; - } - - void decode_sec1ed3() - { - // master table number in sec1[3] - out.master_table_number = in.read_byte(1, 3); - // has_optional in sec1[7] - // Once we know if the optional section is available, we can scan - // section lengths for the rest of the message - in.scan_other_sections(in.read_byte(1, 7) & 0x80); - optional_section_length = in.sec[3] - in.sec[2]; - if (optional_section_length) - optional_section_length -= 4; - // subcentre in sec1[4] - out.originating_subcentre = in.read_byte(1, 4); - // centre in sec1[5] - out.originating_centre = in.read_byte(1, 5); - // Update sequence number sec1[6] - out.update_sequence_number = in.read_byte(1, 6); - out.master_table_version_number = in.read_byte(1, 10); - out.master_table_version_number_local = in.read_byte(1, 11); - out.data_category = in.read_byte(1, 8); - out.data_subcategory = 0xff; - out.data_subcategory_local = in.read_byte(1, 9); - - out.rep_year = in.read_byte(1, 12); - // Fix the century with a bit of euristics - if (out.rep_year > 50) - out.rep_year += 1900; - else - out.rep_year += 2000; - out.rep_month = in.read_byte(1, 13); - out.rep_day = in.read_byte(1, 14); - out.rep_hour = in.read_byte(1, 15); - out.rep_minute = in.read_byte(1, 16); - if (in.read_byte(1, 17) != 0) - out.rep_year = in.read_byte(1, 17) * 100 + (out.rep_year % 100); - } - - void decode_sec1ed4() - { - // master table number in sec1[3] - out.master_table_number = in.read_byte(1, 3); - // centre in sec1[4-5] - out.originating_centre = in.read_number(1, 4, 2); - // subcentre in sec1[6-7] - out.originating_subcentre = in.read_number(1, 6, 2); - // update sequence number sec1[8] - out.update_sequence_number = in.read_byte(1, 8); - // has_optional in sec1[9] - // Once we know if the optional section is available, we can scan - // section lengths for the rest of the message - in.scan_other_sections(in.read_byte(1, 9) & 0x80); - optional_section_length = in.sec[3] - in.sec[2]; - if (optional_section_length) - optional_section_length -= 4; - // category in sec1[10] - out.data_category = in.read_byte(1, 10); - // international data sub-category in sec1[11] - out.data_subcategory = in.read_byte(1, 11); - // local data sub-category in sec1[12] - out.data_subcategory_local = in.read_byte(1, 12); - // version number of master table in sec1[13] - out.master_table_version_number = in.read_byte(1, 13); - // version number of local table in sec1[14] - out.master_table_version_number_local = in.read_byte(1, 14); - // year in sec1[15-16] - out.rep_year = in.read_number(1, 15, 2); - // month in sec1[17] - out.rep_month = in.read_byte(1, 17); - // day in sec1[18] - out.rep_day = in.read_byte(1, 18); - // hour in sec1[19] - out.rep_hour = in.read_byte(1, 19); - // minute in sec1[20] - out.rep_minute = in.read_byte(1, 20); - // sec in sec1[21] - out.rep_second = in.read_byte(1, 21); - } - - /* Decode the message header only */ - void decode_header() - { - // Read BUFR section 0 (Indicator section) - if (memcmp(in.data + in.sec[0], "BUFR", 4) != 0) - in.parse_error(0, 0, "data does not start with BUFR header (\"%.4s\" was read instead)", in.data + in.sec[0]); - - // Check the BUFR edition number - out.edition_number = in.read_byte(0, 7); - if (out.edition_number != 2 && out.edition_number != 3 && out.edition_number != 4) - in.parse_error(0, 7, "Only BUFR edition 2, 3, and 4 are supported (this message is edition %d)", out.edition_number); - - // Looks like a BUFR, scan section starts - in.scan_lead_sections(); - - // Read bufr section 1 (Identification section) - in.check_available_data(1, 0, out.edition_number == 4 ? 22 : 18, "section 1 of BUFR message (identification section)"); - - switch (out.edition_number) - { - case 2: decode_sec1ed3(); break; - case 3: decode_sec1ed3(); break; - case 4: decode_sec1ed4(); break; - default: - error_consistency::throwf("BUFR edition is %d, but I can only decode 2, 3 and 4", out.edition_number); - } - - TRACE("BUFR:edition %d, optional section %ub, update sequence number %d\n", - out.edition, optional_section_length, out.update_sequence_number); - TRACE(" origin %d.%d tables %d.%d type %d.%d %04d-%02d-%02d %02d:%02d\n", - out.centre, out.subcentre, - out.master_table, out.local_table, - out.type, out.subtype, - out.rep_year, out.rep_month, out.rep_day, out.rep_hour, out.rep_minute); - - // Read BUFR section 2 (Optional section) - if (optional_section_length) - { - out.optional_section = string( - (const char*)in.data + in.sec[2] + 4, - in.read_number(2, 0, 3) - 4); - } - - /* Read BUFR section 3 (Data description section) */ - in.check_available_data(3, 0, 8, "section 3 of BUFR message (data description section)"); - expected_subsets = in.read_number(3, 4, 2); - out.compression = (in.read_byte(3, 6) & 0x40) ? 1 : 0; - for (unsigned i = 0; i < (in.sec[4] - in.sec[3] - 7)/2; i++) - out.datadesc.push_back((Varcode)in.read_number(3, 7 + i * 2, 2)); - TRACE(" s3length %d subsets %zd observed %d compression %d byte7 %x\n", - in.sec[4] - in.sec[3], expected_subsets, (in.read_byte(3, 6) & 0x80) ? 1 : 0, - out.compression, in.read_byte(3, 6)); - /* - IFTRACE{ - TRACE(" -> data descriptor section: "); - bufrex_opcode_print(msg->datadesc, stderr); - TRACE("\n"); - } - */ - // Once we filled the Bulletin header info, load decoding tables and allocate subsets - out.load_tables(); - } - - /* Decode message data section after the header has been decoded */ - void decode_data(); -}; - -/// Decoder for uncompressed data -struct UncompressedBufrDecoder : public bulletin::UncompressedDecoder -{ - /// Input buffer - buffers::BufrInput& in; - - /// If set, it is the associated field for the next variable to be decoded - Var* cur_associated_field = nullptr; - - UncompressedBufrDecoder(Bulletin& bulletin, unsigned subset_no, buffers::BufrInput& in) - : bulletin::UncompressedDecoder(bulletin, subset_no), in(in) - { - } - - ~UncompressedBufrDecoder() - { - delete cur_associated_field; - } - - Var decode_b_value(Varinfo info) - { - Var var(info); - switch (info->type) - { - case Vartype::String: - in.decode_string(var); - break; - case Vartype::Binary: - in.decode_binary(var); - break; - case Vartype::Integer: - case Vartype::Decimal: - in.decode_number(var); - break; - } - return var; - } - - void define_substituted_value(unsigned pos) override - { - // Use the details of the corrisponding variable for decoding - Varinfo info = output_subset[pos].info(); - Var var = decode_b_value(info); - TRACE(" define_substituted_value adding var %01d%02d%03d %s as attribute to %01d%02d%03d\n", - WR_VAR_FXY(var.code()), var.value(), WR_VAR_FXY(output_subset[var_pos].code())); - output_subset[pos].seta(var); - } - - void define_attribute(Varinfo info, unsigned pos) override - { - Var var = decode_b_value(info); - TRACE(" define_attribute adding var %01d%02d%03d %s as attribute to %01d%02d%03d\n", - WR_VAR_FXY(var.code()), var.value(), WR_VAR_FXY(output_subset[var_pos].code())); - output_subset[pos].seta(var); - } - - /** - * Request processing, according to \a info, of a data variable. - */ - void define_variable(Varinfo info) override - { - if (associated_field.bit_count) - { - if (cur_associated_field) - { - delete cur_associated_field; - cur_associated_field = 0; - } - TRACE("decode_b_data:reading %d bits of C04 information\n", associated_field.bit_count); - uint32_t val = in.get_bits(associated_field.bit_count); - TRACE("decode_b_data:read C04 information %x\n", val); - cur_associated_field = associated_field.make_attribute(val).release(); - } - - output_subset.store_variable(decode_b_value(info)); - IFTRACE { - TRACE(" define_variable decoded: "); - output_subset.back().print(stderr); - } - if (cur_associated_field) - { - IFTRACE { - TRACE(" define_variable with associated field: "); - cur_associated_field->print(stderr); - } - unique_ptr af(cur_associated_field); - cur_associated_field = 0; - output_subset.back().seta(move(af)); - } - } - - /** - * Request processing of C05yyy character data - */ - void define_raw_character_data(Varcode code) - { - unsigned cdatalen = WR_VAR_Y(code); - string buf; - buf.resize(cdatalen); - TRACE("decode_c_data:character data %d long\n", cdatalen); - for (unsigned i = 0; i < cdatalen; ++i) - { - uint32_t bitval = in.get_bits(8); - TRACE("decode_c_data:decoded character %d %c\n", (int)bitval, (char)bitval); - buf[i] = bitval; - } - - // Add as C variable to the subset - - // Create a single use varinfo to store the bitmap - Varinfo info = tables.get_chardata(code, cdatalen); - - // Store the character data - Var cdata(info, buf); - output_subset.store_variable(cdata); - - TRACE("decode_c_data:decoded string %s\n", buf.c_str()); - } - - unsigned define_delayed_replication_factor(Varinfo info) override - { - output_subset.store_variable(decode_b_value(info)); - return output_subset.back().enqi(); - } - - unsigned define_associated_field_significance(Varinfo info) override - { - output_subset.store_variable(decode_b_value(info)); - return output_subset.back().enq(63); - } - - unsigned define_bitmap_delayed_replication_factor(Varinfo info) override - { - Var rep_count = decode_b_value(info); - return rep_count.enqi(); - } - - void define_bitmap(unsigned bitmap_size) override - { - Varcode code = bitmaps.pending_definitions; - - TRACE("define_bitmap %d\n", bitmap_size); - - // Bitmap size is now in count - - // Read the bitmap - string buf = in.decode_uncompressed_bitmap(bitmap_size); - - // Create a single use varinfo to store the bitmap - Varinfo info = tables.get_bitmap(code, buf); - - // Store the bitmap - Var bmp(info, buf); - - // Bitmap will stay set as a reference to the variable to use as the - // current bitmap. The subset(s) are taking care of memory managing it. - - IFTRACE { - TRACE("Decoded bitmap count %u: ", bitmap_size); - bmp.print(stderr); - TRACE("\n"); - } - - bitmaps.define(bmp, output_subset, output_subset.size()); - - // Add var to subset(s) - output_subset.store_variable(move(bmp)); - } -}; - -/// Decoder for compressed data -struct CompressedBufrDecoder : public bulletin::CompressedDecoder -{ - /// Input buffer - buffers::BufrInput& in; - - /// Number of subsets in data section - unsigned subset_count; - - CompressedBufrDecoder(BufrBulletin& bulletin, buffers::BufrInput& in) - : bulletin::CompressedDecoder(bulletin), in(in), subset_count(bulletin.subsets.size()) - { - } - - template - void decode_b_value(Varinfo info, Adder& dest) - { - switch (info->type) - { - case Vartype::String: - in.decode_string(info, subset_count, dest); - break; - case Vartype::Binary: - throw error_unimplemented("decode_b_binary TODO"); - case Vartype::Integer: - case Vartype::Decimal: - if (associated_field.bit_count) - { - in.decode_compressed_number(info, associated_field.bit_count, subset_count, [&](unsigned subset_no, Var&& var, uint32_t associated_field_val) { - unique_ptr af(associated_field.make_attribute(associated_field_val)); - if (af.get()) var.seta(move(af)); - dest.add_var(subset_no, move(var)); - }); - } - else - in.decode_compressed_number(info, subset_count, dest); - break; - } - } - - void decode_b_value(Varinfo info, std::function dest) - { - switch (info->type) - { - case Vartype::String: - in.decode_string(info, subset_count, dest); - break; - case Vartype::Binary: - throw error_unimplemented("decode_b_binary TODO"); - case Vartype::Integer: - case Vartype::Decimal: - if (associated_field.bit_count) - { - in.decode_compressed_number(info, associated_field.bit_count, subset_count, [&](unsigned subset_no, Var&& var, uint32_t associated_field_val) { - unique_ptr af(associated_field.make_attribute(associated_field_val)); - if (af.get()) var.seta(move(af)); - dest(subset_no, move(var)); - }); - } - else - in.decode_compressed_number(info, subset_count, dest); - break; - } - } - - /** - * Decode a value that must always be the same acrosso all datasets. - * - * @returns the decoded value - */ - Var decode_semantic_b_value(Varinfo info) - { - Var var(info); - switch (info->type) - { - case Vartype::String: - in.decode_string(var, subset_count); - break; - case Vartype::Binary: - throw error_unimplemented("decode_b_binary TODO"); - case Vartype::Integer: - case Vartype::Decimal: - in.decode_compressed_semantic_number(var, subset_count); - break; - } - return var; - } - - /** - * Add \a var to all datasets, returning a pointer to one version of \a var - * that is memory managed by one of the datasets. - */ - void add_to_all(const Var& var) - { - for (unsigned i = 0; i < subset_count; ++i) - output_bulletin.subsets[i].store_variable(var); - } - - void define_variable(Varinfo info) override - { - struct Adder - { - Bulletin& out; - unsigned subset_count; - Adder(Bulletin& out, unsigned subset_count) : out(out), subset_count(subset_count) {} - - void add_missing(Varinfo info) - { - for (unsigned i = 0; i < subset_count; ++i) - out.subsets[i].store_variable_undef(info); - } - void add_same(const Var& var) - { - for (unsigned i = 0; i < subset_count; ++i) - out.subsets[i].store_variable(Var(var)); - } - void add_var(unsigned subset, Var&& var) - { - out.subsets[subset].store_variable(var); - } - } adder(output_bulletin, subset_count); - decode_b_value(info, adder); - } - - void define_substituted_value(unsigned pos) override - { - // Use the details of the corrisponding variable for decoding - Varinfo info = output_bulletin.subset(0)[pos].info(); - decode_b_value(info, [&](unsigned idx, Var&& var) { - output_bulletin.subsets[idx][pos].seta(var); - }); - } - - void define_attribute(Varinfo info, unsigned pos) override - { - decode_b_value(info, [&](unsigned idx, Var&& var) { - output_bulletin.subsets[idx][pos].seta(var); - }); - } - - void define_raw_character_data(Varcode code) override - { - // TODO: if compressed, extract the data from each subset? Store it in each dataset? - error_unimplemented::throwf("C05%03d character data found in compressed message and it is not clear how it should be handled", WR_VAR_Y(code)); - } - - unsigned define_delayed_replication_factor(Varinfo info) override - { - Var res(decode_semantic_b_value(info)); - add_to_all(res); - return res.enqi(); - } - - unsigned define_associated_field_significance(Varinfo info) override - { - Var res(decode_semantic_b_value(info)); - add_to_all(res); - return res.enq(63); - } - - unsigned define_bitmap_delayed_replication_factor(Varinfo info) override - { - Var rep_count = decode_semantic_b_value(info); - return rep_count.enqi(); - } - void define_bitmap(unsigned bitmap_size) override - { - Varcode code = bitmaps.pending_definitions; - - // Read the bitmap - string buf = in.decode_compressed_bitmap(bitmap_size); - - // Create a single use varinfo to store the bitmap - Varinfo info = tables.get_bitmap(code, buf); - - // Create the bitmap variable - Var bmp(info, buf); - - // Add var to subset(s) - add_to_all(bmp); - - // Bitmap will stay set as a reference to the variable to use as the - // current bitmap. The subset(s) are taking care of memory managing it. - - IFTRACE { - TRACE("Decoded bitmap count %u: ", bitmap_size); - bmp.print(stderr); - TRACE("\n"); - } - - bitmaps.define(move(bmp), output_bulletin.subset(0), output_bulletin.subset(0).size()); - } -}; - -void Decoder::decode_data() -{ - out.obtain_subset(expected_subsets - 1); - - /* Read BUFR section 4 (Data section) */ - TRACE(" decode_data:section 4 is %d bytes long (%02x %02x %02x %02x)\n", - in.read_number(4, 0, 3), - in.read_byte(4, 0), - in.read_byte(4, 1), - in.read_byte(4, 2), - in.read_byte(4, 3)); - - if (out.compression) - { - // Run only once - CompressedBufrDecoder dec(out, in); - dec.associated_field.skip_missing = !conf_add_undef_attrs; - dec.run(); - } else { - // Run once per subset - for (unsigned i = 0; i < out.subsets.size(); ++i) - { - UncompressedBufrDecoder dec(out, i, in); - dec.associated_field.skip_missing = !conf_add_undef_attrs; - dec.run(); - } - } - - IFTRACE { - if (in.bits_left() > 32) - { - fprintf(stderr, "The data section of %s:%zd still contains %d unparsed bits\n", - in.fname, in.start_offset, in.bits_left() - 32); - /* - err = dba_error_parse(msg->file->name, POS + vec->cursor, - "the data section still contains %d unparsed bits", - bitvec_bits_left(vec)); - goto fail; - */ - } - } - - /* Read BUFR section 5 (Data section) */ - in.check_available_data(5, 0, 4, "section 5 of BUFR message (end section)"); - - if (memcmp(in.data + in.sec[5], "7777", 4) != 0) - in.parse_error(5, 0, "section 5 does not contain '7777'"); - - for (unsigned i = 0; i < 5; ++i) - out.section_end[i] = in.sec[i + 1]; - out.section_end[5] = out.section_end[4] + 4; - - //if (subsets_no != out.subsets.size()) - // parse_error(sec5, "header advertised %u subsets but only %zd found", subsets_no, out.subsets.size()); -} - -} - - -std::unique_ptr BufrBulletin::decode_header(const std::string& buf, const BufrCodecOptions& opts, const char* fname, size_t offset) -{ - auto res = BufrBulletin::create(); - res->fname = fname; - res->offset = offset; - Decoder d(buf, fname, offset, *res); - d.read_options(opts); - d.decode_header(); - return res; -} - -std::unique_ptr BufrBulletin::decode(const std::string& buf, const BufrCodecOptions& opts, const char* fname, size_t offset) -{ - auto res = BufrBulletin::create(); - res->fname = fname; - res->offset = offset; - Decoder d(buf, fname, offset, *res); - d.read_options(opts); - d.decode_header(); - d.decode_data(); - return res; -} - -std::unique_ptr BufrBulletin::decode_header(const std::string& buf, const char* fname, size_t offset) -{ - auto res = BufrBulletin::create(); - res->fname = fname; - res->offset = offset; - Decoder d(buf, fname, offset, *res); - d.decode_header(); - return res; -} - -std::unique_ptr BufrBulletin::decode(const std::string& buf, const char* fname, size_t offset) -{ - auto res = BufrBulletin::create(); - res->fname = fname; - res->offset = offset; - Decoder d(buf, fname, offset, *res); - d.decode_header(); - d.decode_data(); - return res; -} - -} diff -Nru wreport-3.6/wreport/bufr_decoder-test.cc wreport-3.15/wreport/bufr_decoder-test.cc --- wreport-3.6/wreport/bufr_decoder-test.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bufr_decoder-test.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,765 +0,0 @@ -#include "tests.h" -#include - -using namespace wreport; -using namespace wreport::tests; -using namespace std; - -namespace { - -typedef tests::TestCodec TestBufr; - -class Tests : public TestCase -{ - using TestCase::TestCase; - - void declare_test(std::string fname, std::function check_contents) - { - add_method(fname, [=]() { - TestBufr test(fname); - test.check_contents = check_contents; - wassert(test.run()); - }); - }; - - void register_tests() override - { - add_method("bufr/corrupted.bufr", []() { - // Corrupted BUFR - - // Read the whole contents of the test file - std::string raw1 = tests::slurpfile("bufr/corrupted.bufr"); - - // Decode the original contents - try { - BufrBulletin::decode(raw1, "bufr/corrupted.bufr"); - } catch (std::exception& e) { - wassert(actual(e.what()).contains("Only BUFR edition 2, 3, and 4 are supported (this message is edition 47)")); - } - }); - - declare_test("bufr/bufr1", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 1); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 21); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 35u); - - wassert(actual_varcode(s[9].code()) == WR_VAR(0, 5, 2)); - wassert(actual(s[9].enqd()) == 68.27); - wassert(actual_varcode(s[10].code()) == WR_VAR(0, 6, 2)); - wassert(actual(s[10].enqd()) == 9.68); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(msg.section_end[0]) == 8u); - wassert(actual(msg.section_end[1]) == 26u); - wassert(actual(msg.section_end[2]) == 78u); - wassert(actual(msg.section_end[3]) == 102u); - wassert(actual(msg.section_end[4]) == 178u); - wassert(actual(msg.section_end[5]) == 182u); - }); - - declare_test("bufr/bufr2", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 1); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 21); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 35u); - - wassert(actual_varcode(s[9].code()) == WR_VAR(0, 5, 2)); - wassert(actual(s[9].enqd()) == 43.02); - wassert(actual_varcode(s[10].code()) == WR_VAR(0, 6, 2)); - wassert(actual(s[10].enqd()) == -12.45); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs0-1.22.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 0); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 1); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 52u); - - wassert(actual_varcode(s[27].code()) == WR_VAR(0, 20, 13)); - wassert(actual(s[27].enqd()) == 250.0); - wassert(actual_varcode(s[34].code()) == WR_VAR(0, 20, 13)); - wassert(actual(s[34].enqd()) == 320.0); - wassert(actual_varcode(s[38].code()) == WR_VAR(0, 20, 13)); - wassert(actual(s[38].enqd()) == 620.0); - wassert(actual_varcode(s[42].code()) == WR_VAR(0, 20, 13)); - wassert(actual(s[42].enqd()) == 920.0); - wassert(actual_varcode(s[46].code()) == WR_VAR(0, 20, 13)); - wassert(actual(s[46].isset()).isfalse()); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs0-3.504.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 0); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 3); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 52u); - - wassert(actual_varcode(s[28].code()) == WR_VAR(0, 20, 12)); - wassert(actual(s[28].enqd()) == 37.0); - wassert(actual_varcode(s[29].code()) == WR_VAR(0, 20, 12)); - wassert(actual(s[29].enqd()) == 22.0); - wassert(actual_varcode(s[30].code()) == WR_VAR(0, 20, 12)); - wassert(actual(s[30].enqd()) == 60.0); - wassert(actual_varcode(s[33].code()) == WR_VAR(0, 20, 12)); - wassert(actual(s[33].enqd()) == 7.0); - wassert(actual_varcode(s[37].code()) == WR_VAR(0, 20, 12)); - wassert(actual(s[37].enqd()) == 5.0); - wassert(actual_varcode(s[41].code()) == WR_VAR(0, 20, 12)); - wassert(actual(s[41].isset()).isfalse()); - wassert(actual_varcode(s[45].code()) == WR_VAR(0, 20, 12)); - wassert(actual(s[45].isset()).isfalse()); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs1-9.2.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 1); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 9); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 37u); - - wassert(actual_varcode(s[0].code()) == WR_VAR(0, 1, 11)); - wassert(actual(string(s[0].enqc())) == "DFPC"); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs1-11.16.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 1); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 11); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 37u); - - wassert(actual_varcode(s[33].code()) == WR_VAR(0, 10, 197)); - wassert(actual(s[33].enqd()) == 46.0); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs1-13.36.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 1); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 13); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 37u); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs1-19.3.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 1); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 19); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 37u); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/synop-old-buoy.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 1); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 21); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 35u); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs2-101.16.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 2); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 101); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 619u); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs2-102.1.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 2); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 102); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 403u); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs2-91.2.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 2); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 91); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 127u); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/airep-old-4-142.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 4); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 142); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 21u); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs4-144.4.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 4); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 144); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 21u); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs4-145.4.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 4); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 145); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 31u); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/obs3-3.1.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 3); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 3); - wassert(actual(msg.subsets.size()) == 180u); - - wassert(actual(msg.subset(0).size()) == 127u); - wassert(actual(msg.subset(1).size()) == 127u); - wassert(actual(msg.subset(2).size()) == 127u); - wassert(actual(msg.subset(179).size()) == 127u); - }); - - declare_test("bufr/obs3-56.2.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 3); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 56); - wassert(actual(msg.subsets.size()) == 35u); - - wassert(actual(msg.subset(0).size()) == 225u); - wassert(actual(msg.subset(1).size()) == 225u); - wassert(actual(msg.subset(2).size()) == 225u); - wassert(actual(msg.subset(34).size()) == 225u); - }); - - declare_test("bufr/crex-has-few-digits.bufr", [](const BufrBulletin& msg) { - /* - * In this case, the ECMWF table has 12 bits for BUFR in Kelvin (up to 409.6) - * but 3 digits for CREX in Celsius (up to 99.0). This means that BUFR can - * encode values too big to fit in CREX, and when it happens dba_var range - * checks kick in and abort decoding. - */ - }); - - declare_test("bufr/test-buoy1.bufr", [](const BufrBulletin& msg) { - // Buoy who could not look up a D table - }); - - declare_test("bufr/ed4.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 8); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 171); - wassert(actual(msg.subsets.size()) == 128u); - - wassert(actual(msg.subset(0).size()) == 26u); - wassert(actual(msg.subset(1).size()) == 26u); - wassert(actual(msg.subset(2).size()) == 26u); - wassert(actual(msg.subset(127).size()) == 26u); - }); - - declare_test("bufr/ed4date.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 8); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 171); - wassert(actual(msg.subsets.size()) == 128u); - - wassert(actual(msg.rep_year) == 2000); - wassert(actual(msg.rep_month) == 1); - wassert(actual(msg.rep_day) == 2); - wassert(actual(msg.rep_hour) == 7); - wassert(actual(msg.rep_minute) == 0); - wassert(actual(msg.rep_second) == 0); - - wassert(actual(msg.subset(0).size()) == 26u); - wassert(actual(msg.subset(1).size()) == 26u); - wassert(actual(msg.subset(2).size()) == 26u); - wassert(actual(msg.subset(127).size()) == 26u); - }); - - declare_test("bufr/ed2radar.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 2); - wassert(actual(msg.data_category) == 6); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1u); - - wassert(actual(msg.rep_year) == 2007); - wassert(actual(msg.rep_month) == 8); - wassert(actual(msg.rep_day) == 13); - wassert(actual(msg.rep_hour) == 18); - wassert(actual(msg.rep_minute) == 30); - wassert(actual(msg.rep_second) == 0); - - wassert(actual(msg.subset(0).size()) == 4606u); - }); - - declare_test("bufr/ed4-compr-string.bufr", [](const BufrBulletin& msg) { - // BUFR4 with compressed strings - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 0); - wassert(actual(msg.data_subcategory) == 2); - wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 5u); - - wassert(actual(msg.rep_year) == 2009); - wassert(actual(msg.rep_month) == 12); - wassert(actual(msg.rep_day) == 3); - wassert(actual(msg.rep_hour) == 3); - wassert(actual(msg.rep_minute) == 0); - wassert(actual(msg.rep_second) == 0); - - wassert(actual(msg.subset(0).size()) == 115u); - wassert(actual(msg.subset(1).size()) == 115u); - wassert(actual(msg.subset(2).size()) == 115u); - wassert(actual(msg.subset(3).size()) == 115u); - wassert(actual(msg.subset(4).size()) == 115u); - }); - - declare_test("bufr/ed4-parseerror1.bufr", [](const BufrBulletin& msg) { - // BUFR4 which gives a parse error - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 0); - wassert(actual(msg.data_subcategory) == 1); - wassert(actual(msg.data_subcategory_local) == 255); - wassert(actual(msg.subsets.size()) == 5u); - - wassert(actual(msg.rep_year) == 2009); - wassert(actual(msg.rep_month) == 12); - wassert(actual(msg.rep_day) == 3); - wassert(actual(msg.rep_hour) == 3); - wassert(actual(msg.rep_minute) == 0); - wassert(actual(msg.rep_second) == 0); - - wassert(actual(msg.subset(0).size()) == 107u); - wassert(actual(msg.subset(1).size()) == 107u); - wassert(actual(msg.subset(2).size()) == 107u); - wassert(actual(msg.subset(3).size()) == 107u); - wassert(actual(msg.subset(4).size()) == 107u); - }); - - declare_test("bufr/ed4-empty.bufr", [](const BufrBulletin& msg) { - // BUFR4 which does not give a parse error but looks empty - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 0); - wassert(actual(msg.data_subcategory) == 1); - wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 7u); - - wassert(actual(msg.rep_year) == 2009); - wassert(actual(msg.rep_month) == 12); - wassert(actual(msg.rep_day) == 3); - wassert(actual(msg.rep_hour) == 3); - wassert(actual(msg.rep_minute) == 0); - wassert(actual(msg.rep_second) == 0); - - wassert(actual(msg.subset(0).size()) == 120u); - wassert(actual(msg.subset(1).size()) == 120u); - wassert(actual(msg.subset(2).size()) == 120u); - wassert(actual(msg.subset(3).size()) == 120u); - wassert(actual(msg.subset(4).size()) == 120u); - wassert(actual(msg.subset(5).size()) == 120u); - wassert(actual(msg.subset(6).size()) == 120u); - }); - - declare_test("bufr/C05060.bufr", [](const BufrBulletin& msg) { - // GTS temp message - }); - -#if 0 - declare_test("bufr/tempforecast.bufr", [](const BufrBulletin& msg) { - // Custom ARPA temp forecast message saved as ARPA generic - // TODO: we cannot test this unless we ship dballe's tables - // reenable after deciding whether to ship them or not - }); -#endif - - declare_test("bufr/C23000.bufr", [](const BufrBulletin& msg) { - // C23000 modifier - }); - - declare_test("bufr/segfault1.bufr", [](const BufrBulletin& msg) { - // BUFR that gave segfault - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 2); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 101); - wassert(actual(msg.subsets.size()) == 1u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 129u); - - wassert(actual_varcode(s[9].code()) == WR_VAR(0, 5, 1)); - wassert(actual(s[9].enqd()) == 41.65); - wassert(actual_varcode(s[10].code()) == WR_VAR(0, 6, 1)); - wassert(actual(s[10].enqd()) == 12.43); - - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[1].enqa(WR_VAR(0, 33, 7))->enqi()) == 70); - }); - - declare_test("bufr/C08022.bufr", [](const BufrBulletin& msg) { - // C08xxx modifier - }); - - declare_test("bufr/C23000-1.bufr", [](const BufrBulletin& msg) { - // C23xxx modifier on a message that gave problems in some machine - }); - - declare_test("bufr/C08032-toolong.bufr", [](const BufrBulletin& msg) { - }); - - declare_test("bufr/synop-longname.bufr", [](const BufrBulletin& msg) { - // Synop with a very long station name - }); - - declare_test("bufr/C04004.bufr", [](const BufrBulletin& msg) { - // C04yyy modifier, B32021=6 - }); - - declare_test("bufr/C04-B31021-1.bufr", [](const BufrBulletin& msg) { - // C04yyy modifier, B32021=1 - }); - - declare_test("bufr/C06006.bufr", [](const BufrBulletin& msg) { - // C06006 modifier - }); - - declare_test("bufr/gps_zenith.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 0); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 14); - wassert(actual(msg.subsets.size()) == 94u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 175u); - - wassert(actual_varcode(s[0].code()) == WR_VAR(0, 1, 15)); - wassert(actual(s[0].enq()) == "AQUI-BKG_"); - }); - - declare_test("bufr/ascat1.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 12); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 223); - wassert(actual(msg.subsets.size()) == 1722u); - - const Subset& s = msg.subset(0); - wassert(actual(s.size()) == 124u); - - wassert(actual_varcode(s[0].code()) == WR_VAR(0, 1, 33)); - wassert(actual(s[0].enq()) == 254); - }); - - declare_test("bufr/unparsable1.bufr", [](const BufrBulletin& msg) { - }); - - declare_test("bufr/C04type21.bufr", [](const BufrBulletin& msg) { - }); - - declare_test("bufr/noassoc.bufr", [](const BufrBulletin& msg) { - // Buffer with a seemingly missing associated field significance - }); - - declare_test("bufr/atms1.bufr", [](const BufrBulletin& msg) { - // ATMS data (http://npp.gsfc.nasa.gov/atms.html) - }); - - declare_test("bufr/atms2.bufr", [](const BufrBulletin& msg) { - // ATMS data (http://npp.gsfc.nasa.gov/atms.html) - }); - - declare_test("bufr/table17.bufr", [](const BufrBulletin& msg) { - // BUFR data using table 17 - }); - - declare_test("bufr/A_ISMN02LFPW080000RRA_C_RJTD_20140808000319_100.bufr", [](const BufrBulletin& msg) { - }); - - declare_test("bufr/bitmap-B33035.bufr", [](const BufrBulletin& msg) { - }); - - declare_test("bufr/gts-buoy1.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 3); - wassert(actual(msg.data_category) == 1); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1u); - }); - - declare_test("bufr/gts-synop-rad1.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 0); - wassert(actual(msg.data_subcategory) == 1); - wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 25u); - }); - - declare_test("bufr/gts-synop-rad2.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 0); - wassert(actual(msg.data_subcategory) == 6); - wassert(actual(msg.data_subcategory_local) == 150); - wassert(actual(msg.subsets.size()) == 1u); - }); - - declare_test("bufr/gts-synop-tchange.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 0); - wassert(actual(msg.data_subcategory) == 1); - wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1u); - }); - - declare_test("bufr/new-003.bufr", [](const BufrBulletin& msg) { - wassert(actual(msg.edition_number) == 4); - wassert(actual(msg.data_category) == 2); - wassert(actual(msg.data_subcategory) == 10); - wassert(actual(msg.data_subcategory_local) == 1); - wassert(actual(msg.subsets.size()) == 1u); - }); - } -} testnewtg("bufr_decoder"); - - -#if 0 -template<> template<> -void to::test<3>() -{ -#if 0 - *** Disabled because this test data uses a template that we do not support - - TestBufrexRaw test; - test.setEdition(3); - test.setCat(1); - test.setSubcat(12); - test.setVars(119); - test.set(WR_VAR(0, 5, 2), 54.10); - test.set(WR_VAR(0, 6, 2), 12.10); - - bufrex_msg msg = read_test_msg_raw("bufr/bufr3", BUFR); - ensureBufrexRawEquals(test, msg); - - bufrex_msg msg1 = reencode_test(msg, BUFR); - ensureBufrexRawEquals(test, msg1); - - bufrex_msg_delete(msg); - bufrex_msg_delete(msg1); -#endif -} - -// Soil temperature message -template<> template<> -void to::test<24>() -{ -#if 0 - // TODO: this seems to be a problem in the input message. - // we can disregard it until someone proves it's our problem and not - // the problem of who generated the message - - /* - TestBufrexMsg test; - test.edition = 2; - test.cat = 6; - test.subcat = 255; - test.localsubcat = 0; - test.subsets = 1; - */ - - //bufrex_msg msg = read_test_msg_header_raw("bufr/test-soil1.bufr", BUFR); - /* - ensureBufrexRawEquals(test, msg); - wassert(actual(msg->rep_year) == 2007); - wassert(actual(msg->rep_month) == 8); - wassert(actual(msg->rep_day) == 13); - wassert(actual(msg->rep_hour) == 18); - wassert(actual(msg->rep_minute) == 30); - wassert(actual(msg->rep_second) == 0); - - test.subset(0).vars = 4606; - */ - - //bufrex_msg msg1 = reencode_test(msg); - //ensureBufrexRawEquals(test, msg1); - - struct Tester : public MsgTester { - void test(const BufrBulletin& msg) - { - /* - wassert(actual(msg.edition_number) == 2); - wassert(actual(msg.data_category) == 6); - wassert(actual(msg.data_subcategory) == 255); - wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1u); - - wassert(actual(msg.rep_year) == 2007); - wassert(actual(msg.rep_month) == 8); - wassert(actual(msg.rep_day) == 13); - wassert(actual(msg.rep_hour) == 18); - wassert(actual(msg.rep_minute) == 30); - wassert(actual(msg.rep_second) == 0); - - wassert(actual(msg.subset(0).size()) == 4606u); - - const Subset& s = msg.subset(0); - - // FIXME Does it have this? - wassert(actual(s[0].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[0].enqa(WR_VAR(0) == 33, 7))->enqi(), 70); - - wassert(actual(s[5].enqa(WR_VAR(0, 33, 7))).istrue()); - wassert(actual(s[5].enqa(WR_VAR(0) == 33, 7))->enqi(), 70); - */ - } - } test; - - // FIXME: recoding might not work - declare_test("bufr/test-soil1.bufr", [](const BufrBulletin& msg) -#endif -} - -#endif - -} diff -Nru wreport-3.6/wreport/bulletin/bitmaps.cc wreport-3.15/wreport/bulletin/bitmaps.cc --- wreport-3.6/wreport/bulletin/bitmaps.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bulletin/bitmaps.cc 2018-05-14 15:34:17.000000000 +0000 @@ -5,6 +5,11 @@ namespace wreport { namespace bulletin { +Bitmap::Bitmap(const Var& bitmap, const Subset& subset) + : Bitmap(bitmap, subset, subset.size()) +{ +} + Bitmap::Bitmap(const Var& bitmap, const Subset& subset, unsigned anchor) : bitmap(bitmap) { @@ -82,6 +87,11 @@ return res; } +void Bitmaps::define(const Var& bitmap, const Subset& subset) +{ + define(bitmap, subset, subset.size()); +} + void Bitmaps::define(const Var& bitmap, const Subset& subset, unsigned anchor_point) { delete current; diff -Nru wreport-3.6/wreport/bulletin/bitmaps.h wreport-3.15/wreport/bulletin/bitmaps.h --- wreport-3.6/wreport/bulletin/bitmaps.h 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bulletin/bitmaps.h 2018-05-14 15:34:17.000000000 +0000 @@ -42,6 +42,7 @@ * the C operator that defines or uses the bitmap) */ Bitmap(const Var& bitmap, const Subset& subset, unsigned anchor); + Bitmap(const Var& bitmap, const Subset& subset); Bitmap(const Bitmap&) = delete; ~Bitmap(); Bitmap& operator=(const Bitmap&) = delete; @@ -79,6 +80,7 @@ ~Bitmaps(); Bitmaps& operator=(const Bitmaps&) = delete; + void define(const Var& bitmap, const Subset& subset); void define(const Var& bitmap, const Subset& subset, unsigned anchor_point); void reuse_last(); diff -Nru wreport-3.6/wreport/bulletin/dds-validator-test.cc wreport-3.15/wreport/bulletin/dds-validator-test.cc --- wreport-3.6/wreport/bulletin/dds-validator-test.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bulletin/dds-validator-test.cc 2018-07-26 09:33:16.000000000 +0000 @@ -1,5 +1,6 @@ -#include "tests.h" +#include "wreport/tests.h" #include "dds-validator.h" +#include "wreport/utils/string.h" #include using namespace wreport; @@ -43,22 +44,26 @@ blacklist.insert("bufr/bad-edition.bufr"); blacklist.insert("bufr/corrupted.bufr"); blacklist.insert("bufr/test-soil1.bufr"); + blacklist.insert("bufr/short0.bufr"); + blacklist.insert("bufr/short1.bufr"); + blacklist.insert("bufr/short2.bufr"); + blacklist.insert("bufr/short3.bufr"); std::vector files = tests::all_test_files("bufr"); - for (std::vector::const_iterator i = files.begin(); - i != files.end(); ++i) + for (const auto& i: files) { + if (str::startswith(i, "bufr/afl-")) continue; WREPORT_TEST_INFO(test_info); - if (blacklist.find(*i) != blacklist.end()) continue; + if (blacklist.find(i) != blacklist.end()) continue; // Read the whole contents of the test file - std::string raw1 = tests::slurpfile(*i); + std::string raw1 = tests::slurpfile(i); // Decode the original contents - unique_ptr msg1 = wcallchecked(BufrBulletin::decode(raw1, i->c_str())); + unique_ptr msg1 = wcallchecked(BufrBulletin::decode(raw1, i.c_str())); // Validate them - test_info() << *i; + test_info() << i; wassert(validate(*msg1)); } }); diff -Nru wreport-3.6/wreport/bulletin/internals.cc wreport-3.15/wreport/bulletin/internals.cc --- wreport-3.6/wreport/bulletin/internals.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bulletin/internals.cc 2018-05-14 15:34:17.000000000 +0000 @@ -1,8 +1,8 @@ #include "internals.h" -#include "var.h" -#include "subset.h" -#include "bulletin.h" -#include "notes.h" +#include "wreport/var.h" +#include "wreport/subset.h" +#include "wreport/bulletin.h" +#include "wreport/notes.h" #include // #define TRACE_INTERPRETER @@ -67,12 +67,13 @@ void UncompressedEncoder::define_variable(Varinfo info) { - const Var& var = get_var(); - - // Deal with an associated field - if (associated_field.bit_count) - encode_associated_field(var); + encode_var(info, get_var()); +} +void UncompressedEncoder::define_variable_with_associated_field(Varinfo info) +{ + const Var& var = get_var(); + encode_associated_field(var); encode_var(info, var); } @@ -99,23 +100,5 @@ } -UncompressedDecoder::UncompressedDecoder(Bulletin& bulletin, unsigned subset_no) - : Interpreter(bulletin.tables, bulletin.datadesc), output_subset(bulletin.obtain_subset(subset_no)) -{ -} - -UncompressedDecoder::~UncompressedDecoder() -{ -} - - -CompressedDecoder::CompressedDecoder(Bulletin& bulletin) - : Interpreter(bulletin.tables, bulletin.datadesc), output_bulletin(bulletin) -{ - TRACE("parser: start on compressed bulletin\n"); -} - -CompressedDecoder::~CompressedDecoder() {} - } } diff -Nru wreport-3.6/wreport/bulletin/internals.h wreport-3.15/wreport/bulletin/internals.h --- wreport-3.6/wreport/bulletin/internals.h 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bulletin/internals.h 2018-05-14 15:34:17.000000000 +0000 @@ -41,6 +41,7 @@ void define_bitmap(unsigned bitmap_size) override; void define_variable(Varinfo info) override; + void define_variable_with_associated_field(Varinfo info) override; unsigned define_delayed_replication_factor(Varinfo info) override; unsigned define_associated_field_significance(Varinfo info) override; unsigned define_bitmap_delayed_replication_factor(Varinfo info) override; @@ -66,24 +67,6 @@ virtual void encode_associated_field(const Var& var); }; -struct UncompressedDecoder : public bulletin::Interpreter -{ - /// Subset where decoded variables go - Subset& output_subset; - - UncompressedDecoder(Bulletin& bulletin, unsigned subset_no); - ~UncompressedDecoder(); -}; - -struct CompressedDecoder : public bulletin::Interpreter -{ - Bulletin& output_bulletin; - - CompressedDecoder(Bulletin& bulletin); - virtual ~CompressedDecoder(); -}; - } } - #endif diff -Nru wreport-3.6/wreport/bulletin/interpreter.cc wreport-3.15/wreport/bulletin/interpreter.cc --- wreport-3.6/wreport/bulletin/interpreter.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bulletin/interpreter.cc 2018-05-14 15:34:17.000000000 +0000 @@ -129,8 +129,11 @@ } else { // Proper variable TRACE("b_variable variable %01d%02d%03d\n", - WR_VAR_F(info->var), WR_VAR_X(info->var), WR_VAR_Y(info->var)); - define_variable(info); + WR_VAR_F(info->code), WR_VAR_X(info->code), WR_VAR_Y(info->code)); + if (associated_field.bit_count) + define_variable_with_associated_field(info); + else + define_variable(info); } } @@ -462,6 +465,11 @@ throw error_unimplemented("define_variable is not implemented in this interpreter"); } +void Interpreter::define_variable_with_associated_field(Varinfo info) +{ + throw error_unimplemented("define_variable_with_associated_field is not implemented in this interpreter"); +} + void Interpreter::define_substituted_value(unsigned pos) { throw error_unimplemented("define_substituted_variable is not implemented in this interpreter"); @@ -477,73 +485,45 @@ throw error_unimplemented("define_raw_character_data is not implemented in this interpreter"); } - -Printer::Printer(const Tables& tables, const Opcodes& opcodes) - : Interpreter(tables, opcodes), out(stdout), indent(0), indent_step(2) -{ -} - -void Printer::print_lead(Varcode code) -{ - fprintf(out, "%*s%d%02d%03d", - indent, "", WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code)); -} - -void Printer::b_variable(Varcode code) -{ - print_lead(code); - if (tables.btable) - { - if (tables.btable->contains(code)) - { - Varinfo info = tables.btable->query(code); - fprintf(out, " %s[%s]", info->desc, info->unit); - } else - fprintf(out, " (missing in B table %s)", tables.btable->pathname().c_str()); - } - putc('\n', out); -} - -void Printer::c_modifier(Varcode code, Opcodes& next) +void Interpreter::print_c_modifier(FILE* out, Varcode code, Opcodes& next) { - print_lead(code); switch (WR_VAR_X(code)) { case 1: - fprintf(out, " change data width to %d\n", WR_VAR_Y(code) ? WR_VAR_Y(code) - 128 : 0); + fprintf(out, "change data width to %d\n", WR_VAR_Y(code) ? WR_VAR_Y(code) - 128 : 0); break; case 2: - fprintf(out, " change data scale to %d\n", WR_VAR_Y(code) ? WR_VAR_Y(code) - 128 : 0); + fprintf(out, "change data scale to %d\n", WR_VAR_Y(code) ? WR_VAR_Y(code) - 128 : 0); break; case 4: - fprintf(out, " %d bits of associated field\n", WR_VAR_Y(code)); + fprintf(out, "%d bits of associated field\n", WR_VAR_Y(code)); break; case 5: - fputs(" character data\n", out); + fputs("character data\n", out); break; case 6: if (next.empty()) - fprintf(out, " local descriptor (unknown) %d bits long\n", WR_VAR_Y(code)); + fprintf(out, "local descriptor (unknown) %d bits long\n", WR_VAR_Y(code)); else - fprintf(out, " local descriptor %d%02d%03d %d bits long\n", WR_VAR_FXY(next[0]), WR_VAR_Y(code)); + fprintf(out, "local descriptor %d%02d%03d %d bits long\n", WR_VAR_FXY(next[0]), WR_VAR_Y(code)); break; case 7: - fprintf(out, " change data scale, reference value and data width by %d\n", WR_VAR_Y(code)); + fprintf(out, "change data scale, reference value and data width by %d\n", WR_VAR_Y(code)); break; case 8: - fprintf(out, " change width of string fields to %d\n", WR_VAR_Y(code)); + fprintf(out, "change width of string fields to %d\n", WR_VAR_Y(code)); break; case 22: - fputs(" quality information with bitmap\n", out); + fputs("quality information with bitmap\n", out); break; case 23: switch (WR_VAR_Y(code)) { case 0: - fputs(" substituted values bitmap\n", out); + fputs("substituted values bitmap\n", out); break; case 255: - fputs(" one substituted value\n", out); + fputs("one substituted value\n", out); break; default: fprintf(out, "C modifier %d%02d%03d not yet supported", WR_VAR_FXY(code)); @@ -551,21 +531,54 @@ } break; case 36: - fputs(" define data present bitmap for reuse\n", out); + fputs("define data present bitmap for reuse\n", out); break; case 37: // Use defined data present bitmap switch (WR_VAR_Y(code)) { - case 0: fputs(" reuse last data present bitmap\n", out); break; - case 255: fputs(" cancel reuse of the last defined bitmap\n", out); break; + case 0: fputs("reuse last data present bitmap\n", out); break; + case 255: fputs("cancel reuse of the last defined bitmap\n", out); break; default: fprintf(out, "C modifier %d%02d%03d uses unsupported y=%03d", WR_VAR_FXY(code), WR_VAR_Y(code)); break; } break; default: - fputs(" (C modifier)\n", out); + fputs("(C modifier)\n", out); break; } +} + + +Printer::Printer(const Tables& tables, const Opcodes& opcodes) + : Interpreter(tables, opcodes), out(stdout), indent(0), indent_step(2) +{ +} + +void Printer::print_lead(Varcode code) +{ + fprintf(out, "%*s%d%02d%03d", + indent, "", WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code)); +} + +void Printer::b_variable(Varcode code) +{ + print_lead(code); + if (tables.btable) + { + if (tables.btable->contains(code)) + { + Varinfo info = tables.btable->query(code); + fprintf(out, " %s[%s]", info->desc, info->unit); + } else + fprintf(out, " (missing in B table %s)", tables.btable->pathname().c_str()); + } + putc('\n', out); +} + +void Printer::c_modifier(Varcode code, Opcodes& next) +{ + print_lead(code); + Interpreter::print_c_modifier(out, code, next); Interpreter::c_modifier(code, next); } @@ -600,6 +613,10 @@ { } +void Printer::define_variable_with_associated_field(Varinfo info) +{ +} + void Printer::define_bitmap(unsigned bitmap_size) { } diff -Nru wreport-3.6/wreport/bulletin/interpreter.h wreport-3.15/wreport/bulletin/interpreter.h --- wreport-3.6/wreport/bulletin/interpreter.h 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bulletin/interpreter.h 2018-05-14 15:34:17.000000000 +0000 @@ -147,13 +147,15 @@ /** * Request processing, according to \a info, of a data variable. - * - * associated_field should be consulted to see if there are also associated - * fields that need processing. */ virtual void define_variable(Varinfo info); /** + * Request processing, according to \a info, of a data variable. + */ + virtual void define_variable_with_associated_field(Varinfo info); + + /** * Request processing, according to \a info, of a data variabile that is * significant for controlling the encoding process. * @@ -195,6 +197,9 @@ /// Request processing of C05yyy raw character data virtual void define_raw_character_data(Varcode code); + + /// Print a description of this C modifier + static void print_c_modifier(FILE* out, Varcode code, Opcodes& nex); }; @@ -239,6 +244,7 @@ void r_replication(Varcode code, Varcode delayed_code, const Opcodes& ops) override; void run_d_expansion(Varcode code) override; void define_variable(Varinfo info) override; + void define_variable_with_associated_field(Varinfo info) override; void define_bitmap(unsigned bitmap_size) override; unsigned define_bitmap_delayed_replication_factor(Varinfo info) override; }; diff -Nru wreport-3.6/wreport/bulletin.cc wreport-3.15/wreport/bulletin.cc --- wreport-3.6/wreport/bulletin.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bulletin.cc 2018-05-14 15:34:17.000000000 +0000 @@ -1,4 +1,5 @@ #include "bulletin.h" +#include "bufr/decoder.h" #include "error.h" #include "tableinfo.h" #include "vartable.h" @@ -341,6 +342,62 @@ tables.load_bufr(BufrTableID(originating_centre, originating_subcentre, master_table_number, master_table_version_number, master_table_version_number_local)); } +std::unique_ptr BufrBulletin::decode_header(const std::string& buf, const BufrCodecOptions& opts, const char* fname, size_t offset) +{ + auto res = BufrBulletin::create(); + res->fname = fname; + res->offset = offset; + bufr::Decoder d(buf, fname, offset, *res); + d.read_options(opts); + d.decode_header(); + return res; +} + +std::unique_ptr BufrBulletin::decode(const std::string& buf, const BufrCodecOptions& opts, const char* fname, size_t offset) +{ + auto res = BufrBulletin::create(); + res->fname = fname; + res->offset = offset; + bufr::Decoder d(buf, fname, offset, *res); + d.read_options(opts); + d.decode_header(); + d.decode_data(); + return res; +} + +std::unique_ptr BufrBulletin::decode_header(const std::string& buf, const char* fname, size_t offset) +{ + auto res = BufrBulletin::create(); + res->fname = fname; + res->offset = offset; + bufr::Decoder d(buf, fname, offset, *res); + d.decode_header(); + return res; +} + +std::unique_ptr BufrBulletin::decode(const std::string& buf, const char* fname, size_t offset) +{ + auto res = BufrBulletin::create(); + res->fname = fname; + res->offset = offset; + bufr::Decoder d(buf, fname, offset, *res); + d.decode_header(); + d.decode_data(); + return res; +} + +std::unique_ptr BufrBulletin::decode_verbose(const std::string& buf, FILE* out, const char* fname, size_t offset) +{ + auto res = BufrBulletin::create(); + res->fname = fname; + res->offset = offset; + bufr::Decoder d(buf, fname, offset, *res); + d.verbose_output = out; + d.decode_header(); + d.decode_data(); + return res; +} + void BufrBulletin::print_details(FILE* out) const { fprintf(out, " BUFR details: ed%hhu t%hhu:%hhu:%hhu %c osl%zd\n", diff -Nru wreport-3.6/wreport/bulletin.h wreport-3.15/wreport/bulletin.h --- wreport-3.6/wreport/bulletin.h 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/bulletin.h 2018-05-14 15:34:17.000000000 +0000 @@ -355,6 +355,22 @@ static std::unique_ptr decode(const std::string& raw, const char* fname="(memory)", size_t offset=0); /** + * Parse an encoded BUFR message, printing decoding information + * + * @param buf + * The buffer to decode + * @param out + * Where the decoder information should be printed + * @param fname + * The file name to use for error messages + * @param offset + * The offset inside the file of the start of the bulletin, used for + * error messages + * @returns The new bulletin with the decoded message + */ + static std::unique_ptr decode_verbose(const std::string& raw, FILE* out, const char* fname="(memory)", size_t offset=0); + + /** * Parse an encoded BUFR message * * @param buf @@ -485,6 +501,22 @@ */ static std::unique_ptr decode(const std::string& raw, const char* fname="(memory)", size_t offset=0); + /** + * Parse an encoded BUFR message, printing decoding information + * + * @param buf + * The buffer to decode + * @param out + * Where the decoder information should be printed + * @param fname + * The file name to use for error messages + * @param offset + * The offset inside the file of the start of the bulletin, used for + * error messages + * @returns The new bulletin with the decoded message + */ + static std::unique_ptr decode_verbose(const std::string& raw, FILE* out, const char* fname="(memory)", size_t offset=0); + protected: CrexBulletin(); }; diff -Nru wreport-3.6/wreport/conv.cc wreport-3.15/wreport/conv.cc --- wreport-3.6/wreport/conv.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/conv.cc 2017-12-06 10:17:35.000000000 +0000 @@ -108,6 +108,8 @@ add_linear("KG/M**3", "G/M**3", 1000, 0); add_linear("ug/m**3", "KG/M**3", 0.000000001, 0); add_linear("KG/M**3", "ug/m**3", 1000000000, 0); + add_linear("mg/l", "KG/M**3", 0.001, 0); + add_linear("KG/M**3", "mg/l", 1000, 0); add_linear("PA", "KPA", 0.001, 0); add_linear("KPA", "PA", 1000, 0); add_linear("M", "MM", 1000, 0); @@ -192,6 +194,7 @@ add_ident("GPM", "MGP"); add_ident("W/m**2", "W/M**2"); add_ident("J M-2", "J/M**2"); + add_ident("ppt", "PART PER THOUSAND"); add_function("octants", "DEGREE TRUE", convert_octants_to_degrees, convert_degrees_to_octants); sort(repo.begin(), repo.end()); diff -Nru wreport-3.6/wreport/conv-test.cc wreport-3.15/wreport/conv-test.cc --- wreport-3.6/wreport/conv-test.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/conv-test.cc 2017-12-06 10:17:35.000000000 +0000 @@ -41,6 +41,12 @@ wassert(actual(convert_units("FLAG TABLE", "FLAG TABLE", 1)) == 1); wassert(actual(convert_units("CODE TABLE", "CODE TABLE", 1)) == 1); + + wassert(actual(convert_units("mg/l", "KG/M**3", 1)) == 0.001); + wassert(actual(convert_units("KG/M**3", "mg/l", 1)) == 1000); + + wassert(actual(convert_units("ppt", "PART PER THOUSAND", 1)) == 1); + wassert(actual(convert_units("PART PER THOUSAND", "ppt", 1)) == 1); }); add_method("vss", []() { // Vertical sounding significance conversion functions diff -Nru wreport-3.6/wreport/crex_decoder.cc wreport-3.15/wreport/crex_decoder.cc --- wreport-3.6/wreport/crex_decoder.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/crex_decoder.cc 2018-05-14 15:34:17.000000000 +0000 @@ -1,5 +1,5 @@ #include "bulletin.h" -#include "bulletin/internals.h" +#include "bulletin/interpreter.h" #include "buffers/crex.h" #include #include "config.h" @@ -118,12 +118,14 @@ } -struct CrexParser : public bulletin::UncompressedDecoder +struct CrexParser : public bulletin::Interpreter { + /// Subset where decoded variables go + Subset& output_subset; buffers::CrexInput& in; CrexParser(Bulletin& bulletin, unsigned subset_idx, buffers::CrexInput& in) - : bulletin::UncompressedDecoder(bulletin, subset_idx), in(in) + : Interpreter(bulletin.tables, bulletin.datadesc), output_subset(bulletin.obtain_subset(subset_idx)), in(in) { } @@ -235,6 +237,17 @@ { auto res = CrexBulletin::create(); res->fname = fname; + res->offset = offset; + buffers::CrexInput in(buf, fname, offset); + bulletin::decode_header(in, *res); + bulletin::decode_data(in, *res); + return res; +} + +std::unique_ptr CrexBulletin::decode_verbose(const std::string& buf, FILE* out, const char* fname, size_t offset) +{ + auto res = CrexBulletin::create(); + res->fname = fname; res->offset = offset; buffers::CrexInput in(buf, fname, offset); bulletin::decode_header(in, *res); diff -Nru wreport-3.6/wreport/crex_decoder-test.cc wreport-3.15/wreport/crex_decoder-test.cc --- wreport-3.6/wreport/crex_decoder-test.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/crex_decoder-test.cc 2016-11-07 10:08:48.000000000 +0000 @@ -80,7 +80,7 @@ wassert(actual(msg.data_category) == 0); wassert(actual(msg.data_subcategory) == 255); wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1); + wassert(actual(msg.subsets.size()) == 1u); const Subset& s = msg.subset(0); wassert(actual(s.size()) == 21u); @@ -99,7 +99,7 @@ wassert(actual(msg.data_category) == 0); wassert(actual(msg.data_subcategory) == 255); wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1); + wassert(actual(msg.subsets.size()) == 1u); const Subset& s = msg.subset(0); wassert(actual(s.size()) == 49u); @@ -118,7 +118,7 @@ wassert(actual(msg.data_category) == 0); wassert(actual(msg.data_subcategory) == 255); wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1); + wassert(actual(msg.subsets.size()) == 1u); const Subset& s = msg.subset(0); wassert(actual(s.size()) == 27u); @@ -137,7 +137,7 @@ wassert(actual(msg.data_category) == 1); wassert(actual(msg.data_subcategory) == 255); wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1); + wassert(actual(msg.subsets.size()) == 1u); const Subset& s = msg.subset(0); wassert(actual(s.size()) == 32u); @@ -156,7 +156,7 @@ wassert(actual(msg.data_category) == 1); wassert(actual(msg.data_subcategory) == 255); wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1); + wassert(actual(msg.subsets.size()) == 1u); const Subset& s = msg.subset(0); wassert(actual(s.size()) == 32u); @@ -175,7 +175,7 @@ wassert(actual(msg.data_category) == 1); wassert(actual(msg.data_subcategory) == 255); wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1); + wassert(actual(msg.subsets.size()) == 1u); const Subset& s = msg.subset(0); wassert(actual(s.size()) == 39u); @@ -194,7 +194,7 @@ wassert(actual(msg.data_category) == 2); wassert(actual(msg.data_subcategory) == 255); wassert(actual(msg.data_subcategory_local) == 0); - wassert(actual(msg.subsets.size()) == 1); + wassert(actual(msg.subsets.size()) == 1u); const Subset& s = msg.subset(0); wassert(actual(s.size()) == 550u); diff -Nru wreport-3.6/wreport/internals/tabledir.cc wreport-3.15/wreport/internals/tabledir.cc --- wreport-3.6/wreport/internals/tabledir.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/internals/tabledir.cc 2017-12-06 10:17:35.000000000 +0000 @@ -309,7 +309,7 @@ if (auto result = query.result()) { bufr_cache[id] = result; - notes::logf("Matched table %s for ce %hu sc %hu mt %hhu mtv %hhu mtlv %hhu", + notes::logf("Matched table %s for ce %hu sc %hu mt %hhu mtv %hhu mtlv %hhu\n", result->btable_id.c_str(), id.originating_centre, id.originating_subcentre, id.master_table_number, id.master_table_version_number, id.master_table_version_number_local); @@ -342,7 +342,7 @@ if (auto result = query.result()) { crex_cache[id] = result; - notes::logf("Matched table %s for mt %hhu mtv %hhu mtlv %hhu", + notes::logf("Matched table %s for mt %hhu mtv %hhu mtlv %hhu\n", result->btable_id.c_str(), id.master_table_number, id.master_table_version_number, id.master_table_version_number_local); diff -Nru wreport-3.6/wreport/Makefile.am wreport-3.15/wreport/Makefile.am --- wreport-3.6/wreport/Makefile.am 2016-01-25 15:04:56.000000000 +0000 +++ wreport-3.15/wreport/Makefile.am 2018-05-14 15:34:17.000000000 +0000 @@ -20,6 +20,9 @@ notes.h \ buffers/bufr.h \ buffers/crex.h \ + bufr/trace.h \ + bufr/input.h \ + bufr/decoder.h \ bulletin.h \ bulletin/associated_fields.h \ bulletin/bitmaps.h \ @@ -41,6 +44,8 @@ utils/lua.h \ utils/string.h \ utils/sys.h \ + utils/term.h \ + utils/testrunner.h \ utils/tests.h \ tests.h \ benchmark.h @@ -64,12 +69,16 @@ tables.cc \ utils/string.cc \ utils/sys.cc \ + utils/term.cc \ utils/tests.cc \ + utils/testrunner.cc \ internals/fs.cc \ internals/tabledir.cc \ subset.cc \ buffers/bufr.cc \ buffers/crex.cc \ + bufr/input.cc \ + bufr/decoder.cc \ bulletin.cc \ bulletin/associated_fields.cc \ bulletin/bitmaps.cc \ @@ -78,7 +87,6 @@ bulletin/dds-validator.cc \ bulletin/dds-printer.cc \ bulletin/dds-scanfeatures.cc \ - bufr_decoder.cc \ bufr_encoder.cc \ crex_decoder.cc \ crex_encoder.cc \ @@ -124,7 +132,8 @@ internals/tabledir-test.cc \ subset-test.cc \ bulletin-test.cc \ - bufr_decoder-test.cc \ + bufr/input-test.cc \ + bufr/decoder-test.cc \ bufr_encoder-test.cc \ crex_decoder-test.cc \ buffers/bufr-test.cc \ diff -Nru wreport-3.6/wreport/Makefile.in wreport-3.15/wreport/Makefile.in --- wreport-3.6/wreport/Makefile.in 2016-08-18 13:33:55.000000000 +0000 +++ wreport-3.15/wreport/Makefile.in 2018-09-19 13:16:11.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -154,28 +154,28 @@ libwreport_la_DEPENDENCIES = $(am__DEPENDENCIES_2) am__libwreport_la_SOURCES_DIST = options.cc error.cc notes.cc conv.cc \ tableinfo.cc varinfo.cc vartable.cc var.cc opcodes.cc \ - dtable.cc tables.cc utils/string.cc utils/sys.cc \ - utils/tests.cc internals/fs.cc internals/tabledir.cc subset.cc \ - buffers/bufr.cc buffers/crex.cc bulletin.cc \ + dtable.cc tables.cc utils/string.cc utils/sys.cc utils/term.cc \ + utils/tests.cc utils/testrunner.cc internals/fs.cc \ + internals/tabledir.cc subset.cc buffers/bufr.cc \ + buffers/crex.cc bufr/input.cc bufr/decoder.cc bulletin.cc \ bulletin/associated_fields.cc bulletin/bitmaps.cc \ bulletin/interpreter.cc bulletin/internals.cc \ bulletin/dds-validator.cc bulletin/dds-printer.cc \ - bulletin/dds-scanfeatures.cc bufr_decoder.cc bufr_encoder.cc \ - crex_decoder.cc crex_encoder.cc tests.cc benchmark.cc \ - utils/lua.cc var-lua.cc + bulletin/dds-scanfeatures.cc bufr_encoder.cc crex_decoder.cc \ + crex_encoder.cc tests.cc benchmark.cc utils/lua.cc var-lua.cc am__dirstamp = $(am__leading_dot)dirstamp @LUA_TRUE@am__objects_1 = utils/lua.lo var-lua.lo am_libwreport_la_OBJECTS = options.lo error.lo notes.lo conv.lo \ tableinfo.lo varinfo.lo vartable.lo var.lo opcodes.lo \ - dtable.lo tables.lo utils/string.lo utils/sys.lo \ - utils/tests.lo internals/fs.lo internals/tabledir.lo subset.lo \ - buffers/bufr.lo buffers/crex.lo bulletin.lo \ + dtable.lo tables.lo utils/string.lo utils/sys.lo utils/term.lo \ + utils/tests.lo utils/testrunner.lo internals/fs.lo \ + internals/tabledir.lo subset.lo buffers/bufr.lo \ + buffers/crex.lo bufr/input.lo bufr/decoder.lo bulletin.lo \ bulletin/associated_fields.lo bulletin/bitmaps.lo \ bulletin/interpreter.lo bulletin/internals.lo \ bulletin/dds-validator.lo bulletin/dds-printer.lo \ - bulletin/dds-scanfeatures.lo bufr_decoder.lo bufr_encoder.lo \ - crex_decoder.lo crex_encoder.lo tests.lo benchmark.lo \ - $(am__objects_1) + bulletin/dds-scanfeatures.lo bufr_encoder.lo crex_decoder.lo \ + crex_encoder.lo tests.lo benchmark.lo $(am__objects_1) libwreport_la_OBJECTS = $(am_libwreport_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -193,13 +193,13 @@ conv-test.cc tableinfo-test.cc varinfo-test.cc \ vartable-test.cc var-test.cc opcodes-test.cc dtable-test.cc \ tables-test.cc internals/fs-test.cc internals/tabledir-test.cc \ - subset-test.cc bulletin-test.cc bufr_decoder-test.cc \ - bufr_encoder-test.cc crex_decoder-test.cc buffers/bufr-test.cc \ - buffers/crex-test.cc bulletin/associated_fields-test.cc \ - bulletin/bitmaps-test.cc bulletin/interpreter-test.cc \ - bulletin/internals-test.cc bulletin/dds-validator-test.cc \ - tests-test.cc utils/tests-main.cc lua-test.cc \ - test-utils-lua.cc + subset-test.cc bulletin-test.cc bufr/input-test.cc \ + bufr/decoder-test.cc bufr_encoder-test.cc crex_decoder-test.cc \ + buffers/bufr-test.cc buffers/crex-test.cc \ + bulletin/associated_fields-test.cc bulletin/bitmaps-test.cc \ + bulletin/interpreter-test.cc bulletin/internals-test.cc \ + bulletin/dds-validator-test.cc tests-test.cc \ + utils/tests-main.cc lua-test.cc test-utils-lua.cc @LUA_TRUE@am__objects_2 = lua-test.$(OBJEXT) test-utils-lua.$(OBJEXT) am_test_wreport_OBJECTS = options-test.$(OBJEXT) error-test.$(OBJEXT) \ conv-test.$(OBJEXT) tableinfo-test.$(OBJEXT) \ @@ -208,9 +208,9 @@ dtable-test.$(OBJEXT) tables-test.$(OBJEXT) \ internals/fs-test.$(OBJEXT) internals/tabledir-test.$(OBJEXT) \ subset-test.$(OBJEXT) bulletin-test.$(OBJEXT) \ - bufr_decoder-test.$(OBJEXT) bufr_encoder-test.$(OBJEXT) \ - crex_decoder-test.$(OBJEXT) buffers/bufr-test.$(OBJEXT) \ - buffers/crex-test.$(OBJEXT) \ + bufr/input-test.$(OBJEXT) bufr/decoder-test.$(OBJEXT) \ + bufr_encoder-test.$(OBJEXT) crex_decoder-test.$(OBJEXT) \ + buffers/bufr-test.$(OBJEXT) buffers/crex-test.$(OBJEXT) \ bulletin/associated_fields-test.$(OBJEXT) \ bulletin/bitmaps-test.$(OBJEXT) \ bulletin/interpreter-test.$(OBJEXT) \ @@ -233,7 +233,50 @@ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/benchmark-main.Po \ + ./$(DEPDIR)/benchmark.Plo ./$(DEPDIR)/bufr_encoder-test.Po \ + ./$(DEPDIR)/bufr_encoder.Plo ./$(DEPDIR)/bulletin-bench.Po \ + ./$(DEPDIR)/bulletin-test.Po ./$(DEPDIR)/bulletin.Plo \ + ./$(DEPDIR)/conv-bench.Po ./$(DEPDIR)/conv-test.Po \ + ./$(DEPDIR)/conv.Plo ./$(DEPDIR)/crex_decoder-test.Po \ + ./$(DEPDIR)/crex_decoder.Plo ./$(DEPDIR)/crex_encoder.Plo \ + ./$(DEPDIR)/dtable-test.Po ./$(DEPDIR)/dtable.Plo \ + ./$(DEPDIR)/error-test.Po ./$(DEPDIR)/error.Plo \ + ./$(DEPDIR)/lua-test.Po ./$(DEPDIR)/notes.Plo \ + ./$(DEPDIR)/opcodes-test.Po ./$(DEPDIR)/opcodes.Plo \ + ./$(DEPDIR)/options-test.Po ./$(DEPDIR)/options.Plo \ + ./$(DEPDIR)/subset-test.Po ./$(DEPDIR)/subset.Plo \ + ./$(DEPDIR)/tableinfo-test.Po ./$(DEPDIR)/tableinfo.Plo \ + ./$(DEPDIR)/tables-test.Po ./$(DEPDIR)/tables.Plo \ + ./$(DEPDIR)/test-utils-lua.Po ./$(DEPDIR)/tests-test.Po \ + ./$(DEPDIR)/tests.Plo ./$(DEPDIR)/var-bench.Po \ + ./$(DEPDIR)/var-lua.Plo ./$(DEPDIR)/var-test.Po \ + ./$(DEPDIR)/var.Plo ./$(DEPDIR)/varinfo-test.Po \ + ./$(DEPDIR)/varinfo.Plo ./$(DEPDIR)/vartable-test.Po \ + ./$(DEPDIR)/vartable.Plo buffers/$(DEPDIR)/bufr-test.Po \ + buffers/$(DEPDIR)/bufr.Plo buffers/$(DEPDIR)/crex-test.Po \ + buffers/$(DEPDIR)/crex.Plo bufr/$(DEPDIR)/decoder-test.Po \ + bufr/$(DEPDIR)/decoder.Plo bufr/$(DEPDIR)/input-test.Po \ + bufr/$(DEPDIR)/input.Plo \ + bulletin/$(DEPDIR)/associated_fields-test.Po \ + bulletin/$(DEPDIR)/associated_fields.Plo \ + bulletin/$(DEPDIR)/bitmaps-test.Po \ + bulletin/$(DEPDIR)/bitmaps.Plo \ + bulletin/$(DEPDIR)/dds-printer.Plo \ + bulletin/$(DEPDIR)/dds-scanfeatures.Plo \ + bulletin/$(DEPDIR)/dds-validator-test.Po \ + bulletin/$(DEPDIR)/dds-validator.Plo \ + bulletin/$(DEPDIR)/internals-test.Po \ + bulletin/$(DEPDIR)/internals.Plo \ + bulletin/$(DEPDIR)/interpreter-test.Po \ + bulletin/$(DEPDIR)/interpreter.Plo \ + internals/$(DEPDIR)/fs-test.Po internals/$(DEPDIR)/fs.Plo \ + internals/$(DEPDIR)/tabledir-test.Po \ + internals/$(DEPDIR)/tabledir.Plo utils/$(DEPDIR)/lua.Plo \ + utils/$(DEPDIR)/string.Plo utils/$(DEPDIR)/sys.Plo \ + utils/$(DEPDIR)/term.Plo utils/$(DEPDIR)/testrunner.Plo \ + utils/$(DEPDIR)/tests-main.Po utils/$(DEPDIR)/tests.Plo am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) @@ -265,13 +308,15 @@ am__dist_noinst_HEADERS_DIST = tests.h test-utils-lua.h benchmark.h am__nobase_dist_wreportinclude_HEADERS_DIST = codetables.h conv.h \ dtable.h error.h notes.h buffers/bufr.h buffers/crex.h \ - bulletin.h bulletin/associated_fields.h bulletin/bitmaps.h \ + bufr/trace.h bufr/input.h bufr/decoder.h bulletin.h \ + bulletin/associated_fields.h bulletin/bitmaps.h \ bulletin/interpreter.h bulletin/internals.h \ bulletin/dds-validator.h bulletin/dds-printer.h \ bulletin/dds-scanfeatures.h opcodes.h options.h subset.h \ internals/fs.h internals/tabledir.h tableinfo.h tables.h var.h \ varinfo.h vartable.h utils/lua.h utils/string.h utils/sys.h \ - utils/tests.h tests.h benchmark.h python.h + utils/term.h utils/testrunner.h utils/tests.h tests.h \ + benchmark.h python.h HEADERS = $(dist_noinst_HEADERS) $(nobase_dist_wreportinclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, @@ -314,7 +359,6 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ -DEP_LIBS = @DEP_LIBS@ DLLTOOL = @DLLTOOL@ DOXYGEN_WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@ DSYMUTIL = @DSYMUTIL@ @@ -361,6 +405,8 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_LIBS = @PKGCONFIG_LIBS@ +PKGCONFIG_REQUIRES = @PKGCONFIG_REQUIRES@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ @@ -446,27 +492,29 @@ # Include the .cc files that contain template definitions nobase_dist_wreportinclude_HEADERS = codetables.h conv.h dtable.h \ - error.h notes.h buffers/bufr.h buffers/crex.h bulletin.h \ + error.h notes.h buffers/bufr.h buffers/crex.h bufr/trace.h \ + bufr/input.h bufr/decoder.h bulletin.h \ bulletin/associated_fields.h bulletin/bitmaps.h \ bulletin/interpreter.h bulletin/internals.h \ bulletin/dds-validator.h bulletin/dds-printer.h \ bulletin/dds-scanfeatures.h opcodes.h options.h subset.h \ internals/fs.h internals/tabledir.h tableinfo.h tables.h var.h \ varinfo.h vartable.h utils/lua.h utils/string.h utils/sys.h \ - utils/tests.h tests.h benchmark.h $(am__append_2) + utils/term.h utils/testrunner.h utils/tests.h tests.h \ + benchmark.h $(am__append_2) lib_LTLIBRARIES = libwreport.la libwreport_la_LIBADD = $(am__append_4) libwreport_la_SOURCES = options.cc error.cc notes.cc conv.cc \ tableinfo.cc varinfo.cc vartable.cc var.cc opcodes.cc \ - dtable.cc tables.cc utils/string.cc utils/sys.cc \ - utils/tests.cc internals/fs.cc internals/tabledir.cc subset.cc \ - buffers/bufr.cc buffers/crex.cc bulletin.cc \ + dtable.cc tables.cc utils/string.cc utils/sys.cc utils/term.cc \ + utils/tests.cc utils/testrunner.cc internals/fs.cc \ + internals/tabledir.cc subset.cc buffers/bufr.cc \ + buffers/crex.cc bufr/input.cc bufr/decoder.cc bulletin.cc \ bulletin/associated_fields.cc bulletin/bitmaps.cc \ bulletin/interpreter.cc bulletin/internals.cc \ bulletin/dds-validator.cc bulletin/dds-printer.cc \ - bulletin/dds-scanfeatures.cc bufr_decoder.cc bufr_encoder.cc \ - crex_decoder.cc crex_encoder.cc tests.cc benchmark.cc \ - $(am__append_3) + bulletin/dds-scanfeatures.cc bufr_encoder.cc crex_decoder.cc \ + crex_encoder.cc tests.cc benchmark.cc $(am__append_3) libwreport_la_LDFLAGS = -version-info @LIBWREPORT_VERSION_INFO@ EXTRA_DIST = internals/compat.h main.dox style.dox features.dox examples.dox TESTS_ENVIRONMENT = $(top_srcdir)/testenv @@ -477,12 +525,12 @@ tableinfo-test.cc varinfo-test.cc vartable-test.cc var-test.cc \ opcodes-test.cc dtable-test.cc tables-test.cc \ internals/fs-test.cc internals/tabledir-test.cc subset-test.cc \ - bulletin-test.cc bufr_decoder-test.cc bufr_encoder-test.cc \ - crex_decoder-test.cc buffers/bufr-test.cc buffers/crex-test.cc \ - bulletin/associated_fields-test.cc bulletin/bitmaps-test.cc \ - bulletin/interpreter-test.cc bulletin/internals-test.cc \ - bulletin/dds-validator-test.cc tests-test.cc \ - utils/tests-main.cc $(am__append_6) + bulletin-test.cc bufr/input-test.cc bufr/decoder-test.cc \ + bufr_encoder-test.cc crex_decoder-test.cc buffers/bufr-test.cc \ + buffers/crex-test.cc bulletin/associated_fields-test.cc \ + bulletin/bitmaps-test.cc bulletin/interpreter-test.cc \ + bulletin/internals-test.cc bulletin/dds-validator-test.cc \ + tests-test.cc utils/tests-main.cc $(am__append_6) test_wreport_LDADD = libwreport.la $(am__append_7) benchmark_SOURCES = \ conv-bench.cc \ @@ -514,8 +562,8 @@ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -527,6 +575,15 @@ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ @@ -569,7 +626,10 @@ @: > utils/$(DEPDIR)/$(am__dirstamp) utils/string.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp) utils/sys.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp) +utils/term.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp) utils/tests.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp) +utils/testrunner.lo: utils/$(am__dirstamp) \ + utils/$(DEPDIR)/$(am__dirstamp) internals/$(am__dirstamp): @$(MKDIR_P) internals @: > internals/$(am__dirstamp) @@ -590,6 +650,14 @@ buffers/$(DEPDIR)/$(am__dirstamp) buffers/crex.lo: buffers/$(am__dirstamp) \ buffers/$(DEPDIR)/$(am__dirstamp) +bufr/$(am__dirstamp): + @$(MKDIR_P) bufr + @: > bufr/$(am__dirstamp) +bufr/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) bufr/$(DEPDIR) + @: > bufr/$(DEPDIR)/$(am__dirstamp) +bufr/input.lo: bufr/$(am__dirstamp) bufr/$(DEPDIR)/$(am__dirstamp) +bufr/decoder.lo: bufr/$(am__dirstamp) bufr/$(DEPDIR)/$(am__dirstamp) bulletin/$(am__dirstamp): @$(MKDIR_P) bulletin @: > bulletin/$(am__dirstamp) @@ -615,15 +683,6 @@ libwreport.la: $(libwreport_la_OBJECTS) $(libwreport_la_DEPENDENCIES) $(EXTRA_libwreport_la_DEPENDENCIES) $(AM_V_CXXLD)$(libwreport_la_LINK) -rpath $(libdir) $(libwreport_la_OBJECTS) $(libwreport_la_LIBADD) $(LIBS) -clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list - benchmark$(EXEEXT): $(benchmark_OBJECTS) $(benchmark_DEPENDENCIES) $(EXTRA_benchmark_DEPENDENCIES) @rm -f benchmark$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(benchmark_OBJECTS) $(benchmark_LDADD) $(LIBS) @@ -631,6 +690,10 @@ internals/$(DEPDIR)/$(am__dirstamp) internals/tabledir-test.$(OBJEXT): internals/$(am__dirstamp) \ internals/$(DEPDIR)/$(am__dirstamp) +bufr/input-test.$(OBJEXT): bufr/$(am__dirstamp) \ + bufr/$(DEPDIR)/$(am__dirstamp) +bufr/decoder-test.$(OBJEXT): bufr/$(am__dirstamp) \ + bufr/$(DEPDIR)/$(am__dirstamp) buffers/bufr-test.$(OBJEXT): buffers/$(am__dirstamp) \ buffers/$(DEPDIR)/$(am__dirstamp) buffers/crex-test.$(OBJEXT): buffers/$(am__dirstamp) \ @@ -656,6 +719,8 @@ -rm -f *.$(OBJEXT) -rm -f buffers/*.$(OBJEXT) -rm -f buffers/*.lo + -rm -f bufr/*.$(OBJEXT) + -rm -f bufr/*.lo -rm -f bulletin/*.$(OBJEXT) -rm -f bulletin/*.lo -rm -f internals/*.$(OBJEXT) @@ -666,73 +731,83 @@ distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/benchmark-main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/benchmark.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufr_decoder-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufr_decoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufr_encoder-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufr_encoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bulletin-bench.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bulletin-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bulletin.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conv-bench.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conv-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crex_decoder-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crex_decoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crex_encoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dtable-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dtable.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notes.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opcodes-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opcodes.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subset-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subset.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tableinfo-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tableinfo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tables-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tables.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-utils-lua.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var-bench.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var-lua.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/varinfo-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/varinfo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vartable-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vartable.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@buffers/$(DEPDIR)/bufr-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@buffers/$(DEPDIR)/bufr.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@buffers/$(DEPDIR)/crex-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@buffers/$(DEPDIR)/crex.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/associated_fields-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/associated_fields.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/bitmaps-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/bitmaps.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/dds-printer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/dds-scanfeatures.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/dds-validator-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/dds-validator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/internals-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/internals.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/interpreter-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/interpreter.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/fs-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/fs.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/tabledir-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/tabledir.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/lua.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/string.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/sys.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/tests-main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/tests.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/benchmark-main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/benchmark.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufr_encoder-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufr_encoder.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bulletin-bench.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bulletin-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bulletin.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conv-bench.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conv-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conv.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crex_decoder-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crex_decoder.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crex_encoder.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dtable-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dtable.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notes.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opcodes-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opcodes.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subset-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subset.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tableinfo-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tableinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tables-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tables.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-utils-lua.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var-bench.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var-lua.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/varinfo-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/varinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vartable-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vartable.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@buffers/$(DEPDIR)/bufr-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@buffers/$(DEPDIR)/bufr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@buffers/$(DEPDIR)/crex-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@buffers/$(DEPDIR)/crex.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bufr/$(DEPDIR)/decoder-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bufr/$(DEPDIR)/decoder.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bufr/$(DEPDIR)/input-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bufr/$(DEPDIR)/input.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/associated_fields-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/associated_fields.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/bitmaps-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/bitmaps.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/dds-printer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/dds-scanfeatures.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/dds-validator-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/dds-validator.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/internals-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/internals.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/interpreter-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bulletin/$(DEPDIR)/interpreter.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/fs-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/fs.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/tabledir-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/tabledir.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/lua.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/string.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/sys.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/term.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/testrunner.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/tests-main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/tests.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -764,6 +839,7 @@ clean-libtool: -rm -rf .libs _libs -rm -rf buffers/.libs buffers/_libs + -rm -rf bufr/.libs bufr/_libs -rm -rf bulletin/.libs bulletin/_libs -rm -rf internals/.libs internals/_libs -rm -rf utils/.libs utils/_libs @@ -844,7 +920,10 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -911,6 +990,8 @@ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f buffers/$(DEPDIR)/$(am__dirstamp) -rm -f buffers/$(am__dirstamp) + -rm -f bufr/$(DEPDIR)/$(am__dirstamp) + -rm -f bufr/$(am__dirstamp) -rm -f bulletin/$(DEPDIR)/$(am__dirstamp) -rm -f bulletin/$(am__dirstamp) -rm -f internals/$(DEPDIR)/$(am__dirstamp) @@ -927,7 +1008,77 @@ clean-libtool mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) buffers/$(DEPDIR) bulletin/$(DEPDIR) internals/$(DEPDIR) utils/$(DEPDIR) + -rm -f ./$(DEPDIR)/benchmark-main.Po + -rm -f ./$(DEPDIR)/benchmark.Plo + -rm -f ./$(DEPDIR)/bufr_encoder-test.Po + -rm -f ./$(DEPDIR)/bufr_encoder.Plo + -rm -f ./$(DEPDIR)/bulletin-bench.Po + -rm -f ./$(DEPDIR)/bulletin-test.Po + -rm -f ./$(DEPDIR)/bulletin.Plo + -rm -f ./$(DEPDIR)/conv-bench.Po + -rm -f ./$(DEPDIR)/conv-test.Po + -rm -f ./$(DEPDIR)/conv.Plo + -rm -f ./$(DEPDIR)/crex_decoder-test.Po + -rm -f ./$(DEPDIR)/crex_decoder.Plo + -rm -f ./$(DEPDIR)/crex_encoder.Plo + -rm -f ./$(DEPDIR)/dtable-test.Po + -rm -f ./$(DEPDIR)/dtable.Plo + -rm -f ./$(DEPDIR)/error-test.Po + -rm -f ./$(DEPDIR)/error.Plo + -rm -f ./$(DEPDIR)/lua-test.Po + -rm -f ./$(DEPDIR)/notes.Plo + -rm -f ./$(DEPDIR)/opcodes-test.Po + -rm -f ./$(DEPDIR)/opcodes.Plo + -rm -f ./$(DEPDIR)/options-test.Po + -rm -f ./$(DEPDIR)/options.Plo + -rm -f ./$(DEPDIR)/subset-test.Po + -rm -f ./$(DEPDIR)/subset.Plo + -rm -f ./$(DEPDIR)/tableinfo-test.Po + -rm -f ./$(DEPDIR)/tableinfo.Plo + -rm -f ./$(DEPDIR)/tables-test.Po + -rm -f ./$(DEPDIR)/tables.Plo + -rm -f ./$(DEPDIR)/test-utils-lua.Po + -rm -f ./$(DEPDIR)/tests-test.Po + -rm -f ./$(DEPDIR)/tests.Plo + -rm -f ./$(DEPDIR)/var-bench.Po + -rm -f ./$(DEPDIR)/var-lua.Plo + -rm -f ./$(DEPDIR)/var-test.Po + -rm -f ./$(DEPDIR)/var.Plo + -rm -f ./$(DEPDIR)/varinfo-test.Po + -rm -f ./$(DEPDIR)/varinfo.Plo + -rm -f ./$(DEPDIR)/vartable-test.Po + -rm -f ./$(DEPDIR)/vartable.Plo + -rm -f buffers/$(DEPDIR)/bufr-test.Po + -rm -f buffers/$(DEPDIR)/bufr.Plo + -rm -f buffers/$(DEPDIR)/crex-test.Po + -rm -f buffers/$(DEPDIR)/crex.Plo + -rm -f bufr/$(DEPDIR)/decoder-test.Po + -rm -f bufr/$(DEPDIR)/decoder.Plo + -rm -f bufr/$(DEPDIR)/input-test.Po + -rm -f bufr/$(DEPDIR)/input.Plo + -rm -f bulletin/$(DEPDIR)/associated_fields-test.Po + -rm -f bulletin/$(DEPDIR)/associated_fields.Plo + -rm -f bulletin/$(DEPDIR)/bitmaps-test.Po + -rm -f bulletin/$(DEPDIR)/bitmaps.Plo + -rm -f bulletin/$(DEPDIR)/dds-printer.Plo + -rm -f bulletin/$(DEPDIR)/dds-scanfeatures.Plo + -rm -f bulletin/$(DEPDIR)/dds-validator-test.Po + -rm -f bulletin/$(DEPDIR)/dds-validator.Plo + -rm -f bulletin/$(DEPDIR)/internals-test.Po + -rm -f bulletin/$(DEPDIR)/internals.Plo + -rm -f bulletin/$(DEPDIR)/interpreter-test.Po + -rm -f bulletin/$(DEPDIR)/interpreter.Plo + -rm -f internals/$(DEPDIR)/fs-test.Po + -rm -f internals/$(DEPDIR)/fs.Plo + -rm -f internals/$(DEPDIR)/tabledir-test.Po + -rm -f internals/$(DEPDIR)/tabledir.Plo + -rm -f utils/$(DEPDIR)/lua.Plo + -rm -f utils/$(DEPDIR)/string.Plo + -rm -f utils/$(DEPDIR)/sys.Plo + -rm -f utils/$(DEPDIR)/term.Plo + -rm -f utils/$(DEPDIR)/testrunner.Plo + -rm -f utils/$(DEPDIR)/tests-main.Po + -rm -f utils/$(DEPDIR)/tests.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -973,7 +1124,77 @@ installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) buffers/$(DEPDIR) bulletin/$(DEPDIR) internals/$(DEPDIR) utils/$(DEPDIR) + -rm -f ./$(DEPDIR)/benchmark-main.Po + -rm -f ./$(DEPDIR)/benchmark.Plo + -rm -f ./$(DEPDIR)/bufr_encoder-test.Po + -rm -f ./$(DEPDIR)/bufr_encoder.Plo + -rm -f ./$(DEPDIR)/bulletin-bench.Po + -rm -f ./$(DEPDIR)/bulletin-test.Po + -rm -f ./$(DEPDIR)/bulletin.Plo + -rm -f ./$(DEPDIR)/conv-bench.Po + -rm -f ./$(DEPDIR)/conv-test.Po + -rm -f ./$(DEPDIR)/conv.Plo + -rm -f ./$(DEPDIR)/crex_decoder-test.Po + -rm -f ./$(DEPDIR)/crex_decoder.Plo + -rm -f ./$(DEPDIR)/crex_encoder.Plo + -rm -f ./$(DEPDIR)/dtable-test.Po + -rm -f ./$(DEPDIR)/dtable.Plo + -rm -f ./$(DEPDIR)/error-test.Po + -rm -f ./$(DEPDIR)/error.Plo + -rm -f ./$(DEPDIR)/lua-test.Po + -rm -f ./$(DEPDIR)/notes.Plo + -rm -f ./$(DEPDIR)/opcodes-test.Po + -rm -f ./$(DEPDIR)/opcodes.Plo + -rm -f ./$(DEPDIR)/options-test.Po + -rm -f ./$(DEPDIR)/options.Plo + -rm -f ./$(DEPDIR)/subset-test.Po + -rm -f ./$(DEPDIR)/subset.Plo + -rm -f ./$(DEPDIR)/tableinfo-test.Po + -rm -f ./$(DEPDIR)/tableinfo.Plo + -rm -f ./$(DEPDIR)/tables-test.Po + -rm -f ./$(DEPDIR)/tables.Plo + -rm -f ./$(DEPDIR)/test-utils-lua.Po + -rm -f ./$(DEPDIR)/tests-test.Po + -rm -f ./$(DEPDIR)/tests.Plo + -rm -f ./$(DEPDIR)/var-bench.Po + -rm -f ./$(DEPDIR)/var-lua.Plo + -rm -f ./$(DEPDIR)/var-test.Po + -rm -f ./$(DEPDIR)/var.Plo + -rm -f ./$(DEPDIR)/varinfo-test.Po + -rm -f ./$(DEPDIR)/varinfo.Plo + -rm -f ./$(DEPDIR)/vartable-test.Po + -rm -f ./$(DEPDIR)/vartable.Plo + -rm -f buffers/$(DEPDIR)/bufr-test.Po + -rm -f buffers/$(DEPDIR)/bufr.Plo + -rm -f buffers/$(DEPDIR)/crex-test.Po + -rm -f buffers/$(DEPDIR)/crex.Plo + -rm -f bufr/$(DEPDIR)/decoder-test.Po + -rm -f bufr/$(DEPDIR)/decoder.Plo + -rm -f bufr/$(DEPDIR)/input-test.Po + -rm -f bufr/$(DEPDIR)/input.Plo + -rm -f bulletin/$(DEPDIR)/associated_fields-test.Po + -rm -f bulletin/$(DEPDIR)/associated_fields.Plo + -rm -f bulletin/$(DEPDIR)/bitmaps-test.Po + -rm -f bulletin/$(DEPDIR)/bitmaps.Plo + -rm -f bulletin/$(DEPDIR)/dds-printer.Plo + -rm -f bulletin/$(DEPDIR)/dds-scanfeatures.Plo + -rm -f bulletin/$(DEPDIR)/dds-validator-test.Po + -rm -f bulletin/$(DEPDIR)/dds-validator.Plo + -rm -f bulletin/$(DEPDIR)/internals-test.Po + -rm -f bulletin/$(DEPDIR)/internals.Plo + -rm -f bulletin/$(DEPDIR)/interpreter-test.Po + -rm -f bulletin/$(DEPDIR)/interpreter.Plo + -rm -f internals/$(DEPDIR)/fs-test.Po + -rm -f internals/$(DEPDIR)/fs.Plo + -rm -f internals/$(DEPDIR)/tabledir-test.Po + -rm -f internals/$(DEPDIR)/tabledir.Plo + -rm -f utils/$(DEPDIR)/lua.Plo + -rm -f utils/$(DEPDIR)/string.Plo + -rm -f utils/$(DEPDIR)/sys.Plo + -rm -f utils/$(DEPDIR)/term.Plo + -rm -f utils/$(DEPDIR)/testrunner.Plo + -rm -f utils/$(DEPDIR)/tests-main.Po + -rm -f utils/$(DEPDIR)/tests.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -995,15 +1216,15 @@ .MAKE: check-am install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ - clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ - clean-libtool cscopelist-am ctags ctags-am distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am 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-libLTLIBRARIES install-man \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am \ + check-local clean clean-checkPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-libLTLIBRARIES install-man \ install-nobase_dist_wreportincludeHEADERS install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ diff -Nru wreport-3.6/wreport/tests.cc wreport-3.15/wreport/tests.cc --- wreport-3.6/wreport/tests.cc 2016-08-18 13:30:03.000000000 +0000 +++ wreport-3.15/wreport/tests.cc 2018-05-14 15:34:17.000000000 +0000 @@ -253,6 +253,24 @@ auto msg1 = wcallchecked(decode_checked(raw1, fname.c_str())); wassert(check_contents(*msg1)); + test_info() << fname << ": decode original version, verbose version"; + FILE* out = fopen("/dev/null", "w"); + auto msg1a = wcallchecked(decode_checked(raw1, fname.c_str(), out)); + wassert(check_contents(*msg1a)); + fclose(out); + + test_info() << fname << ": comparing normal and verbose decoder output"; + { + notes::Collect c(std::cerr); + unsigned diffs = msg1->diff(*msg1a); + if (diffs) + { + track_bulletin(*msg1, "orig", fname.c_str()); + track_bulletin(*msg1a, "verb", fname.c_str()); + } + wassert(actual(diffs) == 0u); + } + // Encode it again test_info() << fname << ": re-encode original version"; std::string raw = wcallchecked(msg1->encode()); diff -Nru wreport-3.6/wreport/tests.h wreport-3.15/wreport/tests.h --- wreport-3.6/wreport/tests.h 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/tests.h 2018-05-14 15:34:17.000000000 +0000 @@ -71,6 +71,22 @@ } template +std::unique_ptr decode_checked(const std::string& buf, const char* name, FILE* verbose) +{ + try { + return BULLETIN::decode_verbose(buf, verbose, name); + } catch (wreport::error_parse& e) { + try { + auto h = BULLETIN::decode_header(buf, name); + h->print_structured(stderr); + } catch (wreport::error& e) { + std::cerr << "Dump interrupted: " << e.what(); + } + throw; + } +} + +template struct TestCodec { std::string fname; diff -Nru wreport-3.6/wreport/utils/string.cc wreport-3.15/wreport/utils/string.cc --- wreport-3.6/wreport/utils/string.cc 2016-08-18 13:30:03.000000000 +0000 +++ wreport-3.15/wreport/utils/string.cc 2018-05-04 08:35:44.000000000 +0000 @@ -6,6 +6,83 @@ namespace wreport { namespace str { +namespace { + +/** + * Return the substring of 'str' without all leading characters for which + * 'classifier' returns true. + */ +template +std::string lstrip(const std::string& str, const FUN& classifier) +{ + if (str.empty()) + return str; + + size_t beg = 0; + while (beg < str.size() && classifier(str[beg])) + ++beg; + + return str.substr(beg, str.size() - beg + 1); +} + +/** + * Return the substring of 'str' without all trailing characters for which + * 'classifier' returns true. + */ +template +std::string rstrip(const std::string& str, const FUN& classifier) +{ + if (str.empty()) + return str; + + size_t end = str.size(); + while (end > 0 && classifier(str[end - 1])) + --end; + + if (end == 0) + return std::string(); + else + return str.substr(0, end); +} + +/** + * Return the substring of 'str' without all leading and trailing characters + * for which 'classifier' returns true. + */ +template +std::string strip(const std::string& str, const FUN& classifier) +{ + if (str.empty()) + return str; + + size_t beg = 0; + size_t end = str.size() - 1; + while (beg < end && classifier(str[beg])) + ++beg; + while (end >= beg && classifier(str[end])) + --end; + + return str.substr(beg, end-beg+1); +} + +} + + +std::string lstrip(const std::string& str) +{ + return lstrip(str, ::isspace); +} + +std::string rstrip(const std::string& str) +{ + return rstrip(str, ::isspace); +} + +std::string strip(const std::string& str) +{ + return strip(str, ::isspace); +} + std::string basename(const std::string& pathname) { size_t pos = pathname.rfind("/"); diff -Nru wreport-3.6/wreport/utils/string.h wreport-3.15/wreport/utils/string.h --- wreport-3.6/wreport/utils/string.h 2016-08-18 13:30:03.000000000 +0000 +++ wreport-3.15/wreport/utils/string.h 2018-05-04 08:35:44.000000000 +0000 @@ -71,85 +71,19 @@ } /** - * Return the substring of 'str' without all leading characters for which - * 'classifier' returns true. - */ -template -inline std::string lstrip(const std::string& str, const FUN& classifier) -{ - if (str.empty()) - return str; - - size_t beg = 0; - while (beg < str.size() && classifier(str[beg])) - ++beg; - - return str.substr(beg, str.size() - beg + 1); -} - -/** * Return the substring of 'str' without all leading spaces. */ -inline std::string lstrip(const std::string& str) -{ - return lstrip(str, ::isspace); -} - -/** - * Return the substring of 'str' without all trailing characters for which - * 'classifier' returns true. - */ -template -inline std::string rstrip(const std::string& str, const FUN& classifier) -{ - if (str.empty()) - return str; - - size_t end = str.size(); - while (end > 0 && classifier(str[end - 1])) - --end; - - if (end == 0) - return std::string(); - else - return str.substr(0, end); -} +std::string lstrip(const std::string& str); /** * Return the substring of 'str' without all trailing spaces. */ -inline std::string rstrip(const std::string& str) -{ - return rstrip(str, ::isspace); -} - -/** - * Return the substring of 'str' without all leading and trailing characters - * for which 'classifier' returns true. - */ -template -inline std::string strip(const std::string& str, const FUN& classifier) -{ - if (str.empty()) - return str; - - size_t beg = 0; - size_t end = str.size() - 1; - while (beg < end && classifier(str[beg])) - ++beg; - while (end >= beg && classifier(str[end])) - --end; - - return str.substr(beg, end-beg+1); -} +std::string rstrip(const std::string& str); /** * Return the substring of 'str' without all leading and trailing spaces. */ -inline std::string strip(const std::string& str) -{ - return strip(str, ::isspace); -} +std::string strip(const std::string& str); /// Return an uppercased copy of str inline std::string upper(const std::string& str) diff -Nru wreport-3.6/wreport/utils/sys.cc wreport-3.15/wreport/utils/sys.cc --- wreport-3.6/wreport/utils/sys.cc 2016-08-18 13:30:03.000000000 +0000 +++ wreport-3.15/wreport/utils/sys.cc 2018-05-12 13:35:35.000000000 +0000 @@ -9,7 +9,10 @@ #include #include #include +#include #include +#include +#include #include namespace { @@ -236,6 +239,8 @@ throw std::runtime_error(desc); } +bool FileDescriptor::is_open() const { return fd != -1; } + void FileDescriptor::close() { if (fd == -1) return; @@ -339,6 +344,84 @@ return MMap(res, length); } +bool FileDescriptor::ofd_setlk(struct flock& lk) +{ +#ifdef F_OFD_SETLK + if (fcntl(fd, F_OFD_SETLK, &lk) != -1) +#else + if (fcntl(fd, F_SETLK, &lk) != -1) +#endif + return true; + if (errno != EAGAIN && errno != EACCES) + throw_error("cannot acquire lock"); + return false; +} + +bool FileDescriptor::ofd_setlkw(struct flock& lk, bool retry_on_signal) +{ + while (true) + { +#ifdef F_OFD_SETLK + if (fcntl(fd, F_OFD_SETLKW, &lk) != -1) +#else + if (fcntl(fd, F_SETLKW, &lk) != -1) +#endif + return true; + if (errno != EINTR) + throw_error("cannot acquire lock"); + if (!retry_on_signal) + return false; + } +} + +bool FileDescriptor::ofd_getlk(struct flock& lk) +{ +#ifdef F_OFD_SETLK + if (fcntl(fd, F_OFD_GETLK, &lk) == -1) +#else + if (fcntl(fd, F_GETLK, &lk) == -1) +#endif + throw_error("cannot test lock"); + return lk.l_type == F_UNLCK; +} + +void FileDescriptor::futimens(const struct ::timespec ts[2]) +{ + if (::futimens(fd, ts) == -1) + throw_error("cannot change file timestamps"); +} + +void FileDescriptor::fsync() +{ + if (::fsync(fd) == -1) + throw_error("fsync failed"); +} + +void FileDescriptor::fdatasync() +{ + if (::fdatasync(fd) == -1) + throw_error("fdatasync failed"); +} + + +/* + * PreserveFileTimes + */ + +PreserveFileTimes::PreserveFileTimes(FileDescriptor fd) + : fd(fd) +{ + struct stat st; + fd.fstat(st); + ts[0] = st.st_atim; + ts[1] = st.st_mtim; +} + +PreserveFileTimes::~PreserveFileTimes() +{ + fd.futimens(ts); +} + /* * NamedFileDescriptor @@ -375,11 +458,31 @@ /* + * ManagedNamedFileDescriptor + */ + +ManagedNamedFileDescriptor::~ManagedNamedFileDescriptor() +{ + if (fd != -1) ::close(fd); +} + +ManagedNamedFileDescriptor& ManagedNamedFileDescriptor::operator=(ManagedNamedFileDescriptor&& o) +{ + if (&o == this) return *this; + close(); + fd = o.fd; + pathname = std::move(o.pathname); + o.fd = -1; + return *this; +} + + +/* * Path */ Path::Path(const char* pathname, int flags) - : NamedFileDescriptor(-1, pathname) + : ManagedNamedFileDescriptor(-1, pathname) { fd = open(pathname, flags | O_PATH); if (fd == -1) @@ -387,7 +490,7 @@ } Path::Path(const std::string& pathname, int flags) - : NamedFileDescriptor(-1, pathname) + : ManagedNamedFileDescriptor(-1, pathname) { fd = open(pathname.c_str(), flags | O_PATH); if (fd == -1) @@ -395,17 +498,11 @@ } Path::Path(Path& parent, const char* pathname, int flags) - : NamedFileDescriptor(parent.openat(pathname, flags | O_PATH), + : ManagedNamedFileDescriptor(parent.openat(pathname, flags | O_PATH), str::joinpath(parent.name(), pathname)) { } -Path::~Path() -{ - if (fd != -1) - ::close(fd); -} - DIR* Path::fdopendir() { int fd1 = ::openat(fd, ".", O_DIRECTORY); @@ -440,18 +537,57 @@ return res; } +int Path::openat_ifexists(const char* pathname, int flags, mode_t mode) +{ + int res = ::openat(fd, pathname, flags, mode); + if (res == -1) + { + if (errno == ENOENT) + return -1; + throw_error("cannot openat"); + } + return res; +} + +bool Path::faccessat(const char* pathname, int mode, int flags) +{ + return ::faccessat(fd, pathname, mode, flags) == 0; +} + void Path::fstatat(const char* pathname, struct stat& st) { if (::fstatat(fd, pathname, &st, 0) == -1) throw_error("cannot fstatat"); } +bool Path::fstatat_ifexists(const char* pathname, struct stat& st) +{ + if (::fstatat(fd, pathname, &st, 0) == -1) + { + if (errno == ENOENT) + return false; + throw_error("cannot fstatat"); + } + return true; +} + void Path::lstatat(const char* pathname, struct stat& st) { if (::fstatat(fd, pathname, &st, AT_SYMLINK_NOFOLLOW) == -1) throw_error("cannot fstatat"); } +bool Path::lstatat_ifexists(const char* pathname, struct stat& st) +{ + if (::fstatat(fd, pathname, &st, AT_SYMLINK_NOFOLLOW) == -1) + { + if (errno == ENOENT) + return false; + throw_error("cannot fstatat"); + } + return true; +} + void Path::unlinkat(const char* pathname) { if (::unlinkat(fd, pathname, 0) == -1) @@ -472,21 +608,11 @@ : path(&dir) { this->dir = dir.fdopendir(); - - long name_max = fpathconf(dir.fd, _PC_NAME_MAX); - if (name_max == -1) // Limit not defined, or error: take a guess - name_max = 255; - size_t len = offsetof(dirent, d_name) + name_max + 1; - cur_entry = (struct dirent*)malloc(len); - if (cur_entry == NULL) - throw std::bad_alloc(); - operator++(); } Path::iterator::~iterator() { - if (cur_entry) free(cur_entry); if (dir) closedir(dir); } @@ -505,12 +631,12 @@ void Path::iterator::operator++() { - struct dirent* result; - if (readdir_r(dir, cur_entry, &result) != 0) - path->throw_error("cannot readdir_r"); - - if (result == nullptr) + errno = 0; + cur_entry = readdir(dir); + if (cur_entry == nullptr) { + if (errno) path->throw_error("cannot readdir"); + // Turn into an end iterator free(cur_entry); cur_entry = nullptr; @@ -614,6 +740,11 @@ return S_ISSOCK(st.st_mode); } +Path Path::iterator::open_path(int flags) const +{ + return Path(*path, cur_entry->d_name); +} + void Path::rmtree() { @@ -637,23 +768,19 @@ */ File::File(const std::string& pathname) - : NamedFileDescriptor(-1, pathname) + : ManagedNamedFileDescriptor(-1, pathname) { } File::File(const std::string& pathname, int flags, mode_t mode) - : NamedFileDescriptor(-1, pathname) + : ManagedNamedFileDescriptor(-1, pathname) { open(flags, mode); } -File::~File() -{ - if (fd != -1) ::close(fd); -} - void File::open(int flags, mode_t mode) { + close(); fd = ::open(pathname.c_str(), flags, mode); if (fd == -1) throw std::system_error(errno, std::system_category(), "cannot open file " + pathname); @@ -661,6 +788,7 @@ bool File::open_ifexists(int flags, mode_t mode) { + close(); fd = ::open(pathname.c_str(), flags, mode); if (fd != -1) return true; if (errno == ENOENT) return false; @@ -672,10 +800,24 @@ char* fbuf = (char*)alloca(prefix.size() + 7); memcpy(fbuf, prefix.data(), prefix.size()); memcpy(fbuf + prefix.size(), "XXXXXX", 7); - int fd = ::mkstemp(fbuf); + return mkstemp(fbuf); +} + +File File::mkstemp(const char* prefix) +{ + size_t prefix_size = strlen(prefix); + char* fbuf = (char*)alloca(prefix_size + 7); + memcpy(fbuf, prefix, prefix_size); + memcpy(fbuf + prefix_size, "XXXXXX", 7); + return mkstemp(fbuf); +} + +File File::mkstemp(char* pathname_template) +{ + int fd = ::mkstemp(pathname_template); if (fd < 0) - throw std::system_error(errno, std::system_category(), std::string("cannot create temporary file ") + fbuf); - return File(fd, fbuf); + throw std::system_error(errno, std::system_category(), std::string("cannot create temporary file ") + pathname_template); + return File(fd, pathname_template); } std::string read_file(const std::string& file) @@ -686,6 +828,9 @@ struct stat st; in.fstat(st); + if (st.st_size == 0) + return std::string(); + // mmap the input file MMap src = in.mmap(st.st_size, PROT_READ, MAP_SHARED); @@ -699,7 +844,7 @@ void write_file(const std::string& file, const void* data, size_t size, mode_t mode) { - File out(file, O_WRONLY | O_CREAT, mode); + File out(file, O_WRONLY | O_CREAT | O_TRUNC, mode); out.write_all_or_retry(data, size); out.close(); } @@ -723,7 +868,7 @@ out.write_all_or_retry(data, size); out.close(); - if (rename(out.name().c_str(), file.c_str()) < 0) + if (::rename(out.name().c_str(), file.c_str()) < 0) throw std::system_error(errno, std::system_category(), "cannot rename " + out.name() + " to " + file); } @@ -749,6 +894,12 @@ return true; } +void rename(const std::string& src_pathname, const std::string& dst_pathname) +{ + if (::rename(src_pathname.c_str(), dst_pathname.c_str()) != 0) + throw std::system_error(errno, std::system_category(), "cannot rename " + src_pathname + " to " + dst_pathname); +} + bool rename_ifexists(const std::string& src, const std::string& dst) { if (::rename(src.c_str(), dst.c_str()) != 0) @@ -762,6 +913,14 @@ return true; } +void touch(const std::string& pathname, time_t ts) +{ + struct utimbuf t = { ts, ts }; + if (::utime(pathname.c_str(), &t) != 0) + throw std::system_error(errno, std::system_category(), "cannot set mtime/atime of " + pathname); +} + + template static bool impl_mkdir_ifmissing(String pathname, mode_t mode) { @@ -872,13 +1031,97 @@ path.rmtree(); } -#if 0 -std::string mkdtemp( std::string tmpl ) +bool rmtree_ifexists(const std::string& pathname) { - char *_tmpl = reinterpret_cast< char * >( alloca( tmpl.size() + 1 ) ); - strcpy( _tmpl, tmpl.c_str() ); - return ::mkdtemp( _tmpl ); + int fd = open(pathname.c_str(), O_PATH); + if (fd == -1) + { + if (errno == ENOENT) + return false; + throw std::system_error(errno, std::system_category(), "cannot open path " + pathname); + } + Path path(fd, pathname); + path.rmtree(); + return true; } -#endif + +void clock_gettime(::clockid_t clk_id, struct ::timespec& ts) +{ + int res = ::clock_gettime(clk_id, &ts); + if (res == -1) + throw std::system_error(errno, std::system_category(), "clock_gettime failed on clock " + std::to_string(clk_id)); +} + +unsigned long long timesec_elapsed(const struct ::timespec& begin, const struct ::timespec& until) +{ + if (begin.tv_sec > until.tv_sec) + return 0; + + if (begin.tv_sec == until.tv_sec) + { + if (begin.tv_nsec > until.tv_nsec) + return 0; + return until.tv_nsec - begin.tv_nsec; + } + + if (until.tv_nsec < begin.tv_nsec) + return (until.tv_sec - begin.tv_sec - 1) * 1000000000 + (until.tv_nsec + 1000000000 - begin.tv_nsec); + else + return (until.tv_sec - begin.tv_sec) * 1000000000 + until.tv_nsec - begin.tv_nsec; +} + +/* + * Clock + */ + +Clock::Clock(clockid_t clk_id) + : clk_id(clk_id) +{ + clock_gettime(clk_id, ts); +} + +unsigned long long Clock::elapsed() +{ + struct timespec cur_ts; + clock_gettime(clk_id, cur_ts); + return timesec_elapsed(ts, cur_ts); +} + + +/* + * rlimit + */ + +void getrlimit(int resource, struct ::rlimit& rlim) +{ + if (::getrlimit(resource, &rlim) == -1) + throw std::system_error(errno, std::system_category(), "getrlimit failed"); +} + +void setrlimit(int resource, const struct ::rlimit& rlim) +{ + if (::setrlimit(resource, &rlim) == -1) + throw std::system_error(errno, std::system_category(), "setrlimit failed"); +} + +OverrideRlimit::OverrideRlimit(int resource, rlim_t rlim) + : resource(resource) +{ + getrlimit(resource, orig); + set(rlim); +} + +OverrideRlimit::~OverrideRlimit() +{ + setrlimit(resource, orig); +} + +void OverrideRlimit::set(rlim_t rlim) +{ + struct rlimit newval(orig); + newval.rlim_cur = rlim; + setrlimit(resource, newval); +} + } } diff -Nru wreport-3.6/wreport/utils/sys.h wreport-3.15/wreport/utils/sys.h --- wreport-3.6/wreport/utils/sys.h 2016-08-18 13:30:03.000000000 +0000 +++ wreport-3.15/wreport/utils/sys.h 2018-05-12 13:35:35.000000000 +0000 @@ -5,17 +5,19 @@ * @author Enrico Zini * @brief Operating system functions * - * Copyright (C) 2007--2015 Enrico Zini + * Copyright (C) 2007--2018 Enrico Zini */ #include -//#include #include #include #include #include +#include +#include #include #include +#include namespace wreport { namespace sys { @@ -163,11 +165,24 @@ */ [[noreturn]] virtual void throw_runtime_error(const char* desc); + /// Check if the file descriptor is open (that is, if it is not -1) + bool is_open() const; + + /** + * Close the file descriptor, setting its value to -1. + * + * Does nothing if the file descriptor is already closed + */ void close(); void fstat(struct stat& st); void fchmod(mode_t mode); + void futimens(const struct ::timespec ts[2]); + + void fsync(); + void fdatasync(); + int dup(); size_t read(void* buf, size_t count); @@ -222,11 +237,53 @@ MMap mmap(size_t length, int prot, int flags, off_t offset=0); + /** + * Open file description locks F_OFD_SETLK operation. + * + * Returns true if the lock was obtained, false if acquiring the lock + * failed. + */ + bool ofd_setlk(struct ::flock&); + + /** + * Open file description locks F_OFD_SETLKW operation. + * + * Returns true if the lock was obtained, false if a signal was received + * while waiting for the lock. + * + * If retry_on_signal is true, acquiring the lock is automatically retried + * in case of signals, and the function always returns true. + */ + bool ofd_setlkw(struct ::flock&, bool retry_on_signal=true); + + /** + * Open file description locks F_OFD_GETLK operation. + * + * Returns true if the lock would have been obtainable, false if not. + */ + bool ofd_getlk(struct ::flock&); + operator int() const { return fd; } }; /** + * RAII mechanism to save restore file times at the end of some file operations + */ +class PreserveFileTimes +{ +protected: + FileDescriptor fd; + struct ::timespec ts[2]; + +public: + PreserveFileTimes(FileDescriptor fd); + ~PreserveFileTimes(); +}; + + + +/** * File descriptor with a name */ class NamedFileDescriptor : public FileDescriptor @@ -251,10 +308,35 @@ const std::string& name() const { return pathname; } }; + +/** + * File descriptor that gets automatically closed in the object destructor. + */ +struct ManagedNamedFileDescriptor : public NamedFileDescriptor +{ + using NamedFileDescriptor::NamedFileDescriptor; + + ManagedNamedFileDescriptor(ManagedNamedFileDescriptor&&) = default; + ManagedNamedFileDescriptor(const ManagedNamedFileDescriptor&) = delete; + + /** + * The destructor closes the file descriptor, but does not check errors on + * ::close(). + * + * In normal program flow, it is a good idea to explicitly call + * ManagedNamedFileDescriptor::close() in places where it can throw safely. + */ + ~ManagedNamedFileDescriptor(); + + ManagedNamedFileDescriptor& operator=(const ManagedNamedFileDescriptor&) = delete; + ManagedNamedFileDescriptor& operator=(ManagedNamedFileDescriptor&&); +}; + + /** * Wrap a path on the file system opened with O_PATH. */ -struct Path : public NamedFileDescriptor +struct Path : public ManagedNamedFileDescriptor { /** * Iterator for directory entries @@ -306,9 +388,12 @@ /// @return true if we refer to a Unix domain socket. bool issock() const; + + /// Return a Path object for this entry + Path open_path(int flags=0) const; }; - using NamedFileDescriptor::NamedFileDescriptor; + using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor; /** * Open the given pathname with flags | O_PATH. @@ -327,15 +412,6 @@ Path& operator=(const Path&) = delete; Path& operator=(Path&&) = default; - /** - * The destructor closes the file descriptor, but does not check errors on - * ::close(). - * - * In normal program flow, it is a good idea to explicitly call - * Path::close() in places where it can throw safely. - */ - ~Path(); - DIR* fdopendir(); /// Begin iterator on all directory entries @@ -346,11 +422,22 @@ int openat(const char* pathname, int flags, mode_t mode=0777); + /// Same as openat, but returns -1 if the file does not exist + int openat_ifexists(const char* pathname, int flags, mode_t mode=0777); + + bool faccessat(const char* pathname, int mode, int flags=0); + void fstatat(const char* pathname, struct stat& st); + /// fstatat, but in case of ENOENT returns false instead of throwing + bool fstatat_ifexists(const char* pathname, struct stat& st); + /// fstatat with the AT_SYMLINK_NOFOLLOW flag set void lstatat(const char* pathname, struct stat& st); + /// lstatat, but in case of ENOENT returns false instead of throwing + bool lstatat_ifexists(const char* pathname, struct stat& st); + void unlinkat(const char* pathname); /// unlinkat with the AT_REMOVEDIR flag set @@ -366,12 +453,12 @@ /** - * open(2) file descriptors + * File in the file system */ -class File : public NamedFileDescriptor +class File : public ManagedNamedFileDescriptor { public: - using NamedFileDescriptor::NamedFileDescriptor; + using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor; File(File&&) = default; File(const File&) = delete; @@ -384,15 +471,6 @@ /// Wrapper around open(2) File(const std::string& pathname, int flags, mode_t mode=0777); - /** - * The destructor closes the file descriptor, but does not check errors on - * ::close(). - * - * In normal program flow, it is a good idea to explicitly call - * File::close() in places where it can throw safely. - */ - ~File(); - File& operator=(const File&) = delete; File& operator=(File&&) = default; @@ -406,6 +484,8 @@ bool open_ifexists(int flags, mode_t mode=0777); static File mkstemp(const std::string& prefix); + static File mkstemp(const char* prefix); + static File mkstemp(char* pathname_template); }; /// Read whole file into memory. Throws exceptions on failure. @@ -510,63 +590,79 @@ /// Delete the directory \a pathname and all its contents. void rmtree(const std::string& pathname); -#if 0 -/// Nicely wrap access to directories -class Directory -{ -protected: - /// Directory pathname - std::string m_path; +/** + * Delete the directory \a pathname and all its contents. + * + * If the directory does not exist, it returns false, else true. + */ +bool rmtree_ifexists(const std::string& pathname); -public: - class const_iterator - { - /// Directory we are iterating - const Directory* dir; - /// DIR* pointer - void* dirp; - /// dirent structure used for iterating entries - struct dirent* direntbuf; - - public: - // Create an end iterator - const_iterator(); - // Create a begin iterator - const_iterator(const Directory& dir); - // Cleanup properly - ~const_iterator(); - - /// auto_ptr style copy semantics - const_iterator(const const_iterator& i); - const_iterator& operator=(const const_iterator& i); +/** + * Rename src_pathname into dst_pathname. + * + * This is just a wrapper to the rename(2) system call: source and destination + * must be on the same file system. + */ +void rename(const std::string& src_pathname, const std::string& dst_pathname); - /// Move to the next directory entry - const_iterator& operator++(); +/** + * Set mtime and atime for the file + */ +void touch(const std::string& pathname, time_t ts); - /// @return the current file name - std::string operator*() const; +/** + * Call clock_gettime, raising an exception if it fails + */ +void clock_gettime(::clockid_t clk_id, struct ::timespec& ts); - bool operator==(const const_iterator& iter) const; - bool operator!=(const const_iterator& iter) const; - }; +/** + * Return the time elapsed between two timesec structures, in nanoseconds + */ +unsigned long long timesec_elapsed(const struct ::timespec& begin, const struct ::timespec& until); - Directory(const std::string& path); - ~Directory(); +/** + * Access to clock_gettime + */ +struct Clock +{ + ::clockid_t clk_id; + struct ::timespec ts; - /// Pathname of the directory - const std::string& path() const { return m_path; } + /** + * Initialize ts with the value of the given clock + */ + Clock(::clockid_t clk_id); + + /** + * Return the number of nanoseconds elapsed since the last time ts was + * updated + */ + unsigned long long elapsed(); +}; + +/** + * rlimit wrappers + */ + +/// Call getrlimit, raising an exception if it fails +void getrlimit(int resource, struct ::rlimit& rlim); - /// Check if the directory exists - bool exists() const; +/// Call setrlimit, raising an exception if it fails +void setrlimit(int resource, const struct ::rlimit& rlim); - /// Begin iterator - const_iterator begin() const; +/// Override a soft resource limit during the lifetime of the object +struct OverrideRlimit +{ + int resource; + struct ::rlimit orig; + + OverrideRlimit(int resource, rlim_t rlim); + ~OverrideRlimit(); - /// End iterator - const_iterator end() const; + /// Change the limit value again + void set(rlim_t rlim); }; -#endif } } diff -Nru wreport-3.6/wreport/utils/term.cc wreport-3.15/wreport/utils/term.cc --- wreport-3.6/wreport/utils/term.cc 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/utils/term.cc 2018-05-04 08:35:44.000000000 +0000 @@ -0,0 +1,150 @@ +#include "term.h" +#include +#include +#include + +namespace wreport { +namespace term { + + +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_BLUE "\x1b[34m" +#define ANSI_COLOR_MAGENTA "\x1b[35m" +#define ANSI_COLOR_CYAN "\x1b[36m" +#define ANSI_COLOR_RESET "\x1b[0m" + +const unsigned Terminal::black = 1; +const unsigned Terminal::red = 2; +const unsigned Terminal::green = 3; +const unsigned Terminal::yellow = 4; +const unsigned Terminal::blue = 5; +const unsigned Terminal::magenta = 6; +const unsigned Terminal::cyan = 7; +const unsigned Terminal::white = 8; +const unsigned Terminal::bright = 0x10; +static const unsigned color_mask = 0xf; + +Terminal::Restore::Restore(Terminal& term) + : term(term) +{ +} + +Terminal::Restore::~Restore() +{ + if (!term.isatty) return; + fputs("\x1b[0m", term.out); +} + + +Terminal::Terminal(FILE* out) + : out(out) +{ + int fd = fileno(out); + if (fd == -1) + isatty = false; + else + { + int res = ::isatty(fd); + if (res == 1) + isatty = true; + else if (errno == EINVAL || errno == ENOTTY) + isatty = false; + else + throw std::system_error(errno, std::system_category(), "isatty failed"); + } +} + +namespace { + +struct SGR +{ + std::string seq; + bool first = true; + + SGR() : seq("\x1b[") {} + + void append(int code) + { + if (first) + first = false; + else + seq += ";"; + seq += std::to_string(code); + } + + void end() + { + seq += "m"; + } + + void set_fg(int col) + { + if (col & Terminal::bright) + append(1); + if (col & color_mask) + append(29 + (col & color_mask)); + } + + void set_bg(int col) + { + if ((col & Terminal::bright) && (col & color_mask)) + { + append(99 + (col & color_mask)); + } else if (col & color_mask) { + append(89 + (col & color_mask)); + } + } +}; + +} + +Terminal::Restore Terminal::set_color(int fg, int bg) +{ + if (!isatty) return Restore(*this); + + SGR set; + if (fg) set.set_fg(fg); + if (bg) set.set_bg(bg); + set.end(); + fputs(set.seq.c_str(), out); + return Restore(*this); +} + +Terminal::Restore Terminal::set_color_fg(int col) +{ + return set_color(col, 0); +} + +Terminal::Restore Terminal::set_color_bg(int col) +{ + return set_color(0, col); +} + +std::string Terminal::color(int fg, int bg, const std::string& s) +{ + if (!isatty) return s; + + SGR set; + if (fg) set.set_fg(fg); + if (bg) set.set_bg(bg); + set.end(); + set.seq += s; + set.seq += "\x1b[0m"; + return set.seq; +} + +std::string Terminal::color_fg(int col, const std::string& s) +{ + return color(col, 0, s); +} + +std::string Terminal::color_bg(int col, const std::string& s) +{ + return color(0, col, s); +} + + +} +} diff -Nru wreport-3.6/wreport/utils/term.h wreport-3.15/wreport/utils/term.h --- wreport-3.6/wreport/utils/term.h 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/utils/term.h 2018-05-04 08:35:44.000000000 +0000 @@ -0,0 +1,56 @@ +#ifndef WREPORT_TERM_H +#define WREPORT_TERM_H + +/** + * @author Enrico Zini + * @brief Contrl terminal output + * + * Copyright (C) 2018 Enrico Zini + */ + +#include +#include + +namespace wreport { +namespace term { + +struct Terminal +{ + static const unsigned black; + static const unsigned red; + static const unsigned green; + static const unsigned yellow; + static const unsigned blue; + static const unsigned magenta; + static const unsigned cyan; + static const unsigned white; + static const unsigned bright; + + FILE* out; + bool isatty; + + struct Restore + { + Terminal& term; + + Restore(Terminal& term); + ~Restore(); + }; + + Terminal(FILE* out); + + Restore set_color(int fg, int bg); + Restore set_color_fg(int col); + Restore set_color_bg(int col); + + std::string color(int fg, int bg, const std::string& s); + std::string color_fg(int col, const std::string& s); + std::string color_bg(int col, const std::string& s); + + operator FILE*() { return out; } +}; + +} +} + +#endif diff -Nru wreport-3.6/wreport/utils/testrunner.cc wreport-3.15/wreport/utils/testrunner.cc --- wreport-3.6/wreport/utils/testrunner.cc 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/utils/testrunner.cc 2018-05-04 08:35:44.000000000 +0000 @@ -0,0 +1,445 @@ +#include "testrunner.h" +#include "tests.h" +#include "term.h" +#include +#include +#include + +using namespace std; +using namespace wreport; + +namespace wreport { +namespace tests { + +/* + * TestMethodResult + */ + +void TestMethodResult::set_failed(TestFailed& e) +{ + error_message = e.what(); + error_stack = make_shared(e.stack); + if (error_message.empty()) + error_message = "test failed with an empty error message"; +} + +void TestMethodResult::print_failure_details(FILE* out) const +{ + if (exception_typeid.empty()) + fprintf(out, "%s.%s: %s\n", test_case.c_str(), test_method.c_str(), error_message.c_str()); + else + fprintf(out, "%s.%s:[%s] %s\n", test_case.c_str(), test_method.c_str(), exception_typeid.c_str(), error_message.c_str()); + if (error_stack) + for (const auto& frame : *error_stack) + fprintf(out, " %s", frame.format().c_str()); +} + + +/* + * TestCaseResult + */ + +unsigned long long TestCaseResult::elapsed_ns() const +{ + unsigned long long res = 0; + for (const auto tmr: methods) + res += tmr.elapsed_ns; + return res; +} + + +/* + * FilteringTestController + */ + +bool FilteringTestController::test_method_should_run(const std::string& fullname) const +{ + if (!whitelist.empty() && fnmatch(whitelist.c_str(), fullname.c_str(), 0) == FNM_NOMATCH) + return false; + + if (!blacklist.empty() && fnmatch(blacklist.c_str(), fullname.c_str(), 0) != FNM_NOMATCH) + return false; + + return true; +} + + +/* + * SimpleTestController + */ + +static const char* mark_success = "✔"; +static const char* mark_fail = "✘"; + + +SimpleTestController::SimpleTestController(wreport::term::Terminal& output) + : output(output) +{ +} + +bool SimpleTestController::test_case_begin(const TestCase& test_case, const TestCaseResult& test_case_result) +{ + // Skip test case if all its methods should not run + bool should_run = false; + for (const auto& m : test_case.methods) + should_run |= test_method_should_run(test_case.name + "." + m.name); + if (!should_run) return false; + + fprintf(output, "%s: ", test_case.name.c_str()); + fflush(output); + return true; +} + +void SimpleTestController::test_case_end(const TestCase& test_case, const TestCaseResult& test_case_result) +{ + if (test_case_result.skipped) + ; + else if (test_case_result.is_success()) + fprintf(output, "\n"); + else + fprintf(output, "\n"); + fflush(output); +} + +bool SimpleTestController::test_method_begin(const TestMethod& test_method, const TestMethodResult& test_method_result) +{ + string name = test_method_result.test_case + "." + test_method.name; + return test_method_should_run(name); +} + +void SimpleTestController::test_method_end(const TestMethod& test_method, const TestMethodResult& test_method_result) +{ + if (test_method_result.skipped) + putc('s', output); + else if (test_method_result.is_success()) + putc('.', output); + else + { + auto restore = output.set_color_fg(term::Terminal::bright | term::Terminal::red); + fputs(mark_fail, output); + } + fflush(output); +} + + +/* + * VerboseTestController + */ + +VerboseTestController::VerboseTestController(wreport::term::Terminal& output) + : output(output) {} + +static void format_elapsed(char* buf, size_t size, unsigned long long elapsed_ns) +{ + if (elapsed_ns < 1000) + snprintf(buf, size, "%lluns", elapsed_ns); + else if (elapsed_ns < 1000000) + snprintf(buf, size, "%lluµs", elapsed_ns / 1000); + else if (elapsed_ns < 1000000000) + snprintf(buf, size, "%llums", elapsed_ns / 1000000); + else + snprintf(buf, size, "%.2fs", (double)(elapsed_ns / 1000000) / 1000.0); +} + +bool VerboseTestController::test_case_begin(const TestCase& test_case, const TestCaseResult& test_case_result) +{ + // Skip test case if all its methods should not run + bool should_run = false; + for (const auto& m : test_case.methods) + should_run |= test_method_should_run(test_case.name + "." + m.name); + if (!should_run) return false; + + fprintf(output, "%s: setup\n", output.color_fg(term::Terminal::bright, test_case.name).c_str()); + return true; +} + +void VerboseTestController::test_case_end(const TestCase& test_case, const TestCaseResult& test_case_result) +{ + if (test_case_result.skipped) + return; + + char elapsed[32]; + format_elapsed(elapsed, 32, test_case_result.elapsed_ns()); + string mark; + if (test_case_result.is_success()) + mark = output.color_fg(term::Terminal::bright | term::Terminal::green, "success"); + else + mark = output.color_fg(term::Terminal::bright | term::Terminal::red, "failed"); + fprintf(output, "%s: %s (%s)\n", output.color_fg(term::Terminal::bright, test_case.name).c_str(), mark.c_str(), elapsed); +} + +bool VerboseTestController::test_method_begin(const TestMethod& test_method, const TestMethodResult& test_method_result) +{ + string name = test_method_result.test_case + "." + test_method.name; + return test_method_should_run(name); +} + +void VerboseTestController::test_method_end(const TestMethod& test_method, const TestMethodResult& test_method_result) +{ + char elapsed[32]; + format_elapsed(elapsed, 32, test_method_result.elapsed_ns); + + if (test_method_result.skipped) + { + if (test_method_result.skipped_reason.empty()) + fprintf(output, "%s.%s: skipped.\n", test_method_result.test_case.c_str(), test_method.name.c_str()); + else + fprintf(output, "%s.%s: skipped: %s\n", test_method_result.test_case.c_str(), test_method.name.c_str(), test_method_result.skipped_reason.c_str()); + } + else if (test_method_result.is_success()) + { + string mark = output.color_fg(term::Terminal::bright | term::Terminal::green, mark_success); + fprintf(output, "%s.%s: %s (%s)\n", test_method_result.test_case.c_str(), test_method.name.c_str(), mark.c_str(), elapsed); + } + else + { + string mark = output.color_fg(term::Terminal::bright | term::Terminal::red, mark_fail); + fprintf(output, "%s.%s: %s (%s)\n", test_method_result.test_case.c_str(), test_method.name.c_str(), mark.c_str(), elapsed); + test_method_result.print_failure_details(output); + } +} + + +/* + * TestRegistry + */ + +TestRegistry& TestRegistry::get() +{ + static TestRegistry* instance = 0; + if (!instance) + instance = new TestRegistry(); + return *instance; +} + +void TestRegistry::register_test_case(TestCase& test_case) +{ + entries.emplace_back(&test_case); +} + +void TestRegistry::iterate_test_methods(std::function f) +{ + for (auto& e: entries) + { + e->register_tests_once(); + for (const auto& m: e->methods) + f(*e, m); + } +} + +std::vector TestRegistry::run_tests(TestController& controller) +{ + std::vector res; + for (auto& e: entries) + { + e->register_tests_once(); + // TODO: filter on e.name + res.emplace_back(std::move(e->run_tests(controller))); + } + return res; +} + + +namespace { + +struct Title +{ + wreport::term::Terminal& output; + std::string title; + bool printed = false; + + Title(wreport::term::Terminal& output, const std::string& title) + : output(output), title(output.color_fg(term::Terminal::bright, title)) + { + } + + bool maybe_print() + { + if (printed) return false; + fputs("\n * ", output); + fputs(title.c_str(), output); + fputs("\n\n", output); + printed = true; + return true; + } + + void maybe_print_or_separator() + { + if (!maybe_print()) + fputs("\n", output); + } +}; + +} + + +/* + * TestResultStats + */ + +TestResultStats::TestResultStats(const std::vector& results) + : results(results) +{ + for (const auto& tc_res: results) + { + if (!tc_res.fail_setup.empty()) + ++test_cases_failed; + else { + if (!tc_res.fail_teardown.empty()) + ++test_cases_failed; + else + ++test_cases_ok; + + for (const auto& tm_res: tc_res.methods) + { + if (tm_res.skipped) + ++methods_skipped; + else if (tm_res.is_success()) + ++methods_ok; + else + ++methods_failed; + } + } + } + + success = methods_ok && !test_cases_failed && !methods_failed; +} + +void TestResultStats::print_results(wreport::term::Terminal& out) +{ + Title title(out, "Test failures"); + + for (const auto& tc_res: results) + { + if (!tc_res.fail_setup.empty()) + { + title.maybe_print(); + fprintf(out, "%s: %s\n", tc_res.test_case.c_str(), tc_res.fail_setup.c_str()); + } else { + if (!tc_res.fail_teardown.empty()) + { + title.maybe_print(); + fprintf(out, "%s: %s\n", tc_res.test_case.c_str(), tc_res.fail_teardown.c_str()); + } + + for (const auto& tm_res: tc_res.methods) + { + if (tm_res.skipped || tm_res.is_success()) continue; + title.maybe_print_or_separator(); + tm_res.print_failure_details(out); + } + } + } +} + +void TestResultStats::print_stats(wreport::term::Terminal& out) +{ + //const long long unsigned slow_threshold = 10; + const long long unsigned slow_threshold = 100000000; + std::map skipped_by_reason; + unsigned skipped_no_reason = 0; + std::vector slow_test_cases; + std::vector slow_test_methods; + + for (const auto& tc_res: results) + { + if (tc_res.elapsed_ns() > slow_threshold) + slow_test_cases.push_back(&tc_res); + + for (const auto& tm_res: tc_res.methods) + { + if (tm_res.skipped) + { + if (tm_res.skipped_reason.empty()) + ++skipped_no_reason; + else + skipped_by_reason[tm_res.skipped_reason] += 1; + } + if (tm_res.elapsed_ns > slow_threshold) + slow_test_methods.push_back(&tm_res); + } + } + + Title title(out, "Test run statistics"); + + if (!skipped_by_reason.empty()) + { + title.maybe_print_or_separator(); + fprintf(out, "Number of tests skipped, by reason:\n\n"); + std::vector> sorted; + for (const auto& i: skipped_by_reason) + sorted.emplace_back(make_pair(i.second, i.first)); + std::sort(sorted.begin(), sorted.end()); + for (const auto& i: sorted) + fprintf(out, " %2dx %s\n", i.first, i.second.c_str()); + if (skipped_no_reason) + fprintf(out, " %2dx (no reason given)\n", skipped_no_reason); + } + + if (!slow_test_cases.empty()) + { + title.maybe_print_or_separator(); + std::sort(slow_test_cases.begin(), slow_test_cases.end(), [](const TestCaseResult* a, const TestCaseResult* b) { return b->elapsed_ns() < a->elapsed_ns(); }); + size_t count = min((size_t)10, slow_test_cases.size()); + fprintf(out, "%zu slowest test cases:\n\n", count); + for (size_t i = 0; i < count; ++i) + { + char elapsed[32]; + format_elapsed(elapsed, 32, slow_test_cases[i]->elapsed_ns()); + fprintf(out, " %s: %s\n", slow_test_cases[i]->test_case.c_str(), elapsed); + } + } + + if (!slow_test_methods.empty()) + { + title.maybe_print_or_separator(); + std::sort(slow_test_methods.begin(), slow_test_methods.end(), [](const TestMethodResult* a, const TestMethodResult* b) { return b->elapsed_ns < a->elapsed_ns; }); + size_t count = min((size_t)10, slow_test_methods.size()); + fprintf(out, "%zu slowest test methods:\n\n", count); + for (size_t i = 0; i < count; ++i) + { + char elapsed[32]; + format_elapsed(elapsed, 32, slow_test_methods[i]->elapsed_ns); + fprintf(out, " %s.%s: %s\n", slow_test_methods[i]->test_case.c_str(), slow_test_methods[i]->test_method.c_str(), elapsed); + } + } +} + +void TestResultStats::print_summary(wreport::term::Terminal& out) +{ + Title title(out, "Result summary"); + + if (test_cases_failed) + { + title.maybe_print(); + fprintf(out, "%u/%u test cases had issues initializing or cleaning up\n", + test_cases_failed, test_cases_ok + test_cases_failed); + } + + if (methods_failed) + { + title.maybe_print(); + string failed = out.color_fg(term::Terminal::red | term::Terminal::bright, "failed"); + fprintf(out, "%u/%u tests %s\n", methods_failed, methods_ok + methods_failed, failed.c_str()); + } + + if (methods_skipped) + { + title.maybe_print(); + fprintf(out, "%u tests skipped\n", methods_skipped); + } + + if (methods_ok) + { + title.maybe_print(); + string succeeded = out.color_fg(term::Terminal::green | term::Terminal::bright, "succeeded"); + fprintf(out, "%u tests %s\n", methods_ok, succeeded.c_str()); + } else { + title.maybe_print(); + string no = out.color_fg(term::Terminal::red | term::Terminal::bright, "no"); + fprintf(out, "%s tests succeeded\n", no.c_str()); + } +} + +} +} diff -Nru wreport-3.6/wreport/utils/testrunner.h wreport-3.15/wreport/utils/testrunner.h --- wreport-3.6/wreport/utils/testrunner.h 1970-01-01 00:00:00.000000000 +0000 +++ wreport-3.15/wreport/utils/testrunner.h 2018-05-04 08:35:44.000000000 +0000 @@ -0,0 +1,297 @@ +#ifndef WREPORT_TESTSRUNNER_H +#define WREPORT_TESTSRUNNER_H + +#include +#include +#include +#include + +namespace wreport { + +namespace term { +struct Terminal; +} + +namespace tests { + +struct TestFailed; +struct TestStack; +struct TestCase; +struct TestMethod; + + +/** + * Result of running a test method. + */ +struct TestMethodResult +{ + /// Name of the test case + std::string test_case; + + /// Name of the test method + std::string test_method; + + /// If non-empty, the test failed with this error + std::string error_message; + + /// Stack frame of where the error happened + std::shared_ptr error_stack; + + /// If non-empty, the test threw an exception and this is its type ID + std::string exception_typeid; + + /// True if the test has been skipped + bool skipped = false; + + /// If the test has been skipped, this is an optional reason + std::string skipped_reason; + + /// Time in nanoseconds it took the test to run + unsigned long long elapsed_ns = 0; + + + TestMethodResult(const std::string& test_case, const std::string& test_method) + : test_case(test_case), test_method(test_method) {} + + void set_failed(TestFailed& e); + + void set_exception(std::exception& e) + { + error_message = e.what(); + if (error_message.empty()) + error_message = "test threw an exception with an empty error message"; + exception_typeid = typeid(e).name(); + } + + void set_unknown_exception() + { + error_message = "unknown exception caught"; + } + + void set_setup_exception(std::exception& e) + { + error_message = "[setup failed: "; + error_message += e.what(); + error_message += "]"; + } + + void set_teardown_exception(std::exception& e) + { + error_message = "[teardown failed: "; + error_message += e.what(); + error_message += "]"; + } + + bool is_success() const + { + return error_message.empty(); + } + + void print_failure_details(FILE* out) const; +}; + +/** + * Result of running a whole test case + */ +struct TestCaseResult +{ + /// Name of the test case + std::string test_case; + /// Outcome of all the methods that have been run + std::vector methods; + /// Set to a non-empty string if the setup method of the test case failed + std::string fail_setup; + /// Set to a non-empty string if the teardown method of the test case + /// failed + std::string fail_teardown; + /// Set to true if this test case has been skipped + bool skipped = false; + + TestCaseResult(const std::string& test_case) : test_case(test_case) {} + + void set_setup_failed() + { + fail_setup = "test case setup method threw an unknown exception"; + } + + void set_setup_failed(std::exception& e) + { + fail_setup = "test case setup method threw an exception: "; + fail_setup += e.what(); + } + + void set_teardown_failed() + { + fail_teardown = "test case teardown method threw an unknown exception"; + } + + void set_teardown_failed(std::exception& e) + { + fail_teardown = "test case teardown method threw an exception: "; + fail_teardown += e.what(); + } + + void add_test_method(TestMethodResult&& e) + { + methods.emplace_back(std::move(e)); + } + + bool is_success() const + { + if (!fail_setup.empty() || !fail_teardown.empty()) return false; + for (const auto& m: methods) + if (!m.is_success()) + return false; + return true; + } + + unsigned long long elapsed_ns() const; +}; + + +/** + * Abstract interface for the objects that supervise test execution. + * + * This can be used for printing progress, or to skip test methods or test + * cases. + */ +struct TestController +{ + virtual ~TestController() {} + + /** + * Called before running a test case. + * + * @returns true if the test case should be run, false if it should be skipped + */ + virtual bool test_case_begin(const TestCase& test_case, const TestCaseResult& test_case_result) { return true; } + + /** + * Called after running a test case. + */ + virtual void test_case_end(const TestCase& test_case, const TestCaseResult& test_case_result) {} + + /** + * Called before running a test method. + * + * @returns true if the test method should be run, false if it should be skipped + */ + virtual bool test_method_begin(const TestMethod& test_method, const TestMethodResult& test_method_result) { return true; } + + /** + * Called after running a test method. + */ + virtual void test_method_end(const TestMethod& test_method, const TestMethodResult& test_method_result) {} +}; + +/** + * Test controller that filters tests via a blacklist/whitelist system + * containing glob patterns on testcase.testmethod names + */ +struct FilteringTestController : public TestController +{ + /// Any method not matching this glob expression will not be run + std::string whitelist; + + /// Any method matching this glob expression will not be run + std::string blacklist; + + bool test_method_should_run(const std::string& fullname) const; +}; + + +/** + * Simple default implementation of TestController. + * + * It does progress printing to stdout and basic glob-based test method + * filtering. + */ +struct SimpleTestController : public FilteringTestController +{ + wreport::term::Terminal& output; + + SimpleTestController(wreport::term::Terminal& output); + + bool test_case_begin(const TestCase& test_case, const TestCaseResult& test_case_result) override; + void test_case_end(const TestCase& test_case, const TestCaseResult& test_case_result) override; + bool test_method_begin(const TestMethod& test_method, const TestMethodResult& test_method_result) override; + void test_method_end(const TestMethod& test_method, const TestMethodResult& test_method_result) override; +}; + + +/** + * Verbose implementation of TestController. + * + * It does progress printing to stdout and basic glob-based test method + * filtering. + */ +struct VerboseTestController : public FilteringTestController +{ + wreport::term::Terminal& output; + + VerboseTestController(wreport::term::Terminal& output); + + bool test_case_begin(const TestCase& test_case, const TestCaseResult& test_case_result) override; + void test_case_end(const TestCase& test_case, const TestCaseResult& test_case_result) override; + bool test_method_begin(const TestMethod& test_method, const TestMethodResult& test_method_result) override; + void test_method_end(const TestMethod& test_method, const TestMethodResult& test_method_result) override; +}; + + +/** + * Test registry. + * + * It collects information about all known test cases and takes care of running + * them. + */ +struct TestRegistry +{ + /// All known test cases + std::vector entries; + + /** + * Register a new test case. + * + * No memory management is done: test_case needs to exist for the whole + * lifetime of TestRegistry. + */ + void register_test_case(TestCase& test_case); + + /** + * Iterate on all test methods known by this registry. + * + * This method does not change the tests, but it cannot be const because it + * calls register_tests_once on each TestCase. + */ + void iterate_test_methods(std::function); + + /** + * Run all the registered tests using the given controller + */ + std::vector run_tests(TestController& controller); + + /// Get the singleton instance of TestRegistry + static TestRegistry& get(); +}; + + +struct TestResultStats +{ + const std::vector& results; + unsigned methods_ok = 0; + unsigned methods_failed = 0; + unsigned methods_skipped = 0; + unsigned test_cases_ok = 0; + unsigned test_cases_failed = 0; + bool success = false; + + TestResultStats(const std::vector& results); + + void print_results(wreport::term::Terminal& out); + void print_stats(wreport::term::Terminal& out); + void print_summary(wreport::term::Terminal& out); +}; + +} +} +#endif diff -Nru wreport-3.6/wreport/utils/tests.cc wreport-3.15/wreport/utils/tests.cc --- wreport-3.6/wreport/utils/tests.cc 2016-08-18 13:30:03.000000000 +0000 +++ wreport-3.15/wreport/utils/tests.cc 2018-05-12 13:35:35.000000000 +0000 @@ -3,16 +3,17 @@ * @brief Utility functions for the unit tests * * Copyright (C) 2006--2007 Peter Rockai (mornfall) - * Copyright (C) 2003--2015 Enrico Zini + * Copyright (C) 2003--2017 Enrico Zini */ #include "tests.h" +#include "testrunner.h" #include "string.h" #include "sys.h" -#include #include #include #include +#include #include using namespace std; @@ -73,6 +74,14 @@ } +/* + * TestSkipped + */ + +TestSkipped::TestSkipped() {} +TestSkipped::TestSkipped(const std::string& reason) : reason(reason) {} + + #if 0 std::string Location::fail_msg(const std::string& error) const { @@ -142,11 +151,14 @@ struct Regexp { + std::string regex; regex_t compiled; + regmatch_t matches[2]; Regexp(const char* regex) + : regex(regex) { - if (int err = regcomp(&compiled, regex, REG_EXTENDED | REG_NOSUB)) + if (int err = regcomp(&compiled, this->regex.c_str(), REG_EXTENDED)) raise_error(err); } ~Regexp() @@ -156,7 +168,7 @@ bool search(const char* s) { - return regexec(&compiled, s, 0, nullptr, 0) != REG_NOMATCH; + return regexec(&compiled, s, 2, matches, 0) != REG_NOMATCH; } void raise_error(int code) @@ -308,6 +320,16 @@ assert_not_contains(_actual, expected); } +void ActualStdString::operator==(const std::vector& expected) const +{ + return operator==(std::string(expected.begin(), expected.end())); +} + +void ActualStdString::operator!=(const std::vector& expected) const +{ + return operator!=(std::string(expected.begin(), expected.end())); +} + void ActualStdString::startswith(const std::string& expected) const { assert_startswith(_actual, expected); @@ -381,78 +403,128 @@ throw TestFailed("file " + _actual + " exists and it should not"); } -#if 0 -void test_assert_file_exists(WIBBLE_TEST_LOCPRM, const std::string& fname) +void ActualFile::startswith(const std::string& data) const { - if (not sys::fs::exists(fname)) - { - std::stringstream ss; - ss << "file '" << fname << "' does not exists"; - wreport_test_location.fail_test(ss.str()); - } + sys::File in(_actual, O_RDONLY); + string buf(data.size(), 0); + in.read_all_or_throw((void*)buf.data(), buf.size()); + *((char*)buf.data() + buf.size()) = 0; + if (buf != data) + throw TestFailed("file " + _actual + " starts with '" + str::encode_cstring(buf) + "' instead of '" + str::encode_cstring(data) + "'"); } -void test_assert_not_file_exists(WIBBLE_TEST_LOCPRM, const std::string& fname) +void ActualFile::empty() const { - if (sys::fs::exists(fname)) - { - std::stringstream ss; - ss << "file '" << fname << "' does exists"; - wreport_test_location.fail_test(ss.str()); - } + size_t size = sys::size(_actual); + if (size > 0) + throw TestFailed("file " + _actual + " is " + std::to_string(size) + "b instead of being empty"); } -#if 0 -struct TestFileExists +void ActualFile::not_empty() const { - std::string pathname; - bool inverted; - TestFileExists(const std::string& pathname, bool inverted=false) : pathname(pathname), inverted(inverted) {} - TestFileExists operator!() { return TestFileExists(pathname, !inverted); } - void check(WREPORT_TEST_LOCPRM) const; -}; -#endif + size_t size = sys::size(_actual); + if (size == 0) + throw TestFailed("file " + _actual + " is empty and it should not be"); +} -void TestFileExists::check(WIBBLE_TEST_LOCPRM) const +void ActualFile::contents_equal(const std::string& data) const { - if (!inverted) + std::string content = sys::read_file(_actual); + if (content != data) + throw TestFailed("file " + _actual + " contains '" + str::encode_cstring(content) + "' instead of '" + str::encode_cstring(data) + "'"); +} + +void ActualFile::contents_equal(const std::vector& data) const +{ + return contents_equal(std::string(data.begin(), data.end())); +} + +void ActualFile::contents_equal(const std::initializer_list& lines) const +{ + std::vector actual_lines; + std::string content = str::rstrip(sys::read_file(_actual)); + + str::Split splitter(content, "\n"); + std::copy(splitter.begin(), splitter.end(), back_inserter(actual_lines)); + + if (actual_lines.size() != lines.size()) + throw TestFailed("file " + _actual + " contains " + std::to_string(actual_lines.size()) + " lines ('" + str::encode_cstring(content) + "') instead of " + std::to_string(lines.size()) + " lines ('" + str::encode_cstring(content) + "')"); + + auto ai = actual_lines.begin(); + auto ei = lines.begin(); + for (unsigned i = 0; i < actual_lines.size(); ++i, ++ai, ++ei) { - if (sys::fs::exists(pathname)) return; - std::stringstream ss; - ss << "file '" << pathname << "' does not exists"; - wreport_test_location.fail_test(ss.str()); - } else { - if (not sys::fs::exists(pathname)) return; - std::stringstream ss; - ss << "file '" << pathname << "' exists"; - wreport_test_location.fail_test(ss.str()); + string actual_line = str::rstrip(*ai); + string expected_line = str::rstrip(*ei); + if (*ai != *ei) + throw TestFailed("file " + _actual + " actual contents differ from expected at line #" + std::to_string(i + 1) + " ('" + str::encode_cstring(actual_line) + "' instead of '" + str::encode_cstring(expected_line) + "')"); + } } -#endif -TestRegistry& TestRegistry::get() +void ActualFile::contents_match(const std::string& data_re) const { - static TestRegistry* instance = 0; - if (!instance) - instance = new TestRegistry(); - return *instance; + std::string content = sys::read_file(_actual); + Regexp re(data_re.c_str()); + if (re.search(content.c_str())) return; + std::stringstream ss; + ss << "file " + _actual << " contains " << str::encode_cstring(content) + << " which does not match " << data_re; + throw TestFailed(ss.str()); } -void TestRegistry::register_test_case(TestCase& test_case) +void ActualFile::contents_match(const std::initializer_list& lines_re) const { - entries.emplace_back(&test_case); + std::vector actual_lines; + std::string content = str::rstrip(sys::read_file(_actual)); + + str::Split splitter(content, "\n"); + std::copy(splitter.begin(), splitter.end(), back_inserter(actual_lines)); + + auto ai = actual_lines.begin(); + auto ei = lines_re.begin(); + unsigned lineno = 1; + while (ei != lines_re.end()) + { + Regexp re(ei->c_str()); + string actual_line = ai == actual_lines.end() ? "" : str::rstrip(*ai); + if (re.search(content.c_str())) + { + if (re.matches[0].rm_so == re.matches[0].rm_eo) + ++ei; + else + { + if (ai != actual_lines.end()) ++ai; + ++ei; + ++lineno; + } + continue; + } + + std::stringstream ss; + ss << "file " << _actual << " actual contents differ from expected at line #" << lineno + << " ('" << str::encode_cstring(actual_line) + << "' does not match '" << str::encode_cstring(*ei) << "')"; + throw TestFailed(ss.str()); + } } -std::vector TestRegistry::run_tests(TestController& controller) + +/* + * TestCase + */ + +TestCase::TestCase(const std::string& name) + : name(name) { - std::vector res; - for (auto& e: entries) - { - e->register_tests(); - // TODO: filter on e.name - res.emplace_back(std::move(e->run_tests(controller))); - } - return res; + TestRegistry::get().register_test_case(*this); +} + +void TestCase::register_tests_once() +{ + if (tests_registered) return; + tests_registered = true; + register_tests(); } TestCaseResult TestCase::run_tests(TestController& controller) @@ -466,22 +538,33 @@ return res; } + bool skip_all = false; + string skip_all_reason; try { setup(); - } catch (TestSkipped) { - res.skipped = true; - controller.test_case_end(*this, res); - return res; + } catch (TestSkipped& e) { + skip_all = true; + skip_all_reason = e.reason; } catch (std::exception& e) { res.set_setup_failed(e); controller.test_case_end(*this, res); return res; } - for (auto& m: methods) + if (skip_all) { - // TODO: filter on m.name - res.add_test_method(run_test(controller, m)); + for (auto& method: methods) + { + TestMethodResult tmr(name, method.name); + controller.test_method_begin(method, tmr); + tmr.skipped = true; + tmr.skipped_reason = skip_all_reason; + controller.test_method_end(method, tmr); + res.add_test_method(move(tmr)); + } + } else { + for (auto& m: methods) + res.add_test_method(run_test(controller, m)); } try { @@ -506,10 +589,22 @@ } bool run = true; + if (!method.test_function) + { + // Skip methods with empty test functions + res.skipped = true; + controller.test_method_end(method, res); + return res; + } + + // Take time now for measuring elapsed time of the test method + sys::Clock timer(CLOCK_MONOTONIC); + try { method_setup(res); - } catch (TestSkipped) { + } catch (TestSkipped& e) { res.skipped = true; + res.skipped_reason = e.reason; controller.test_method_end(method, res); return res; } catch (std::exception& e) { @@ -521,8 +616,9 @@ { try { method.test_function(); - } catch (TestSkipped) { + } catch (TestSkipped& e) { res.skipped = true; + res.skipped_reason = e.reason; } catch (TestFailed& e) { // Location::fail_test() was called res.set_failed(e); @@ -541,61 +637,11 @@ res.set_teardown_exception(e); } + res.elapsed_ns = timer.elapsed(); + controller.test_method_end(method, res); return res; } -bool SimpleTestController::test_method_should_run(const std::string& fullname) const -{ - if (!whitelist.empty() && fnmatch(whitelist.c_str(), fullname.c_str(), 0) == FNM_NOMATCH) - return false; - - if (!blacklist.empty() && fnmatch(blacklist.c_str(), fullname.c_str(), 0) != FNM_NOMATCH) - return false; - - return true; -} - -bool SimpleTestController::test_case_begin(const TestCase& test_case, const TestCaseResult& test_case_result) -{ - // Skip test case if all its methods should not run - bool should_run = false; - for (const auto& m : test_case.methods) - should_run |= test_method_should_run(test_case.name + "." + m.name); - if (!should_run) return false; - - fprintf(stdout, "%s: ", test_case.name.c_str()); - fflush(stdout); - return true; -} - -void SimpleTestController::test_case_end(const TestCase& test_case, const TestCaseResult& test_case_result) -{ - if (test_case_result.skipped) - ; - else if (test_case_result.is_success()) - fprintf(stdout, "\n"); - else - fprintf(stdout, "\n"); - fflush(stdout); -} - -bool SimpleTestController::test_method_begin(const TestMethod& test_method, const TestMethodResult& test_method_result) -{ - string name = test_method_result.test_case + "." + test_method.name; - return test_method_should_run(name); -} - -void SimpleTestController::test_method_end(const TestMethod& test_method, const TestMethodResult& test_method_result) -{ - if (test_method_result.skipped) - putc('s', stdout); - else if (test_method_result.is_success()) - putc('.', stdout); - else - putc('x', stdout); - fflush(stdout); -} - } } diff -Nru wreport-3.6/wreport/utils/tests.h wreport-3.15/wreport/utils/tests.h --- wreport-3.6/wreport/utils/tests.h 2016-08-18 13:30:03.000000000 +0000 +++ wreport-3.15/wreport/utils/tests.h 2018-05-12 13:35:35.000000000 +0000 @@ -6,7 +6,7 @@ * @brief Utility functions for the unit tests * * Copyright (C) 2006--2007 Peter Rockai (mornfall) - * Copyright (C) 2003--2013 Enrico Zini + * Copyright (C) 2003--2017 Enrico Zini */ #include @@ -133,6 +133,10 @@ */ struct TestSkipped : public std::exception { + std::string reason; + + TestSkipped(); + TestSkipped(const std::string& reason); }; /** @@ -144,6 +148,13 @@ wreport::tests::LocationInfo& name = wreport_test_location_info +/** + * The following assert_* functions throw TestFailed without capturing + * file/line numbers, and need to be used inside wassert to give good error + * messages. Do not use them in actual test cases, but you can use them to + * implement test assertions. + */ + /// Test function that ensures that the actual value is true template void assert_true(const A& actual) @@ -307,6 +318,10 @@ { ActualStdString(const std::string& s) : Actual(s) {} + using Actual::operator==; + void operator==(const std::vector& expected) const; + using Actual::operator!=; + void operator!=(const std::vector& expected) const; void startswith(const std::string& expected) const; void endswith(const std::string& expected) const; void contains(const std::string& expected) const; @@ -328,6 +343,7 @@ inline ActualCString actual(const char* actual) { return ActualCString(actual); } inline ActualCString actual(char* actual) { return ActualCString(actual); } inline ActualStdString actual(const std::string& actual) { return ActualStdString(actual); } +inline ActualStdString actual(const std::vector& actual) { return ActualStdString(std::string(actual.begin(), actual.end())); } inline ActualDouble actual(double actual) { return ActualDouble(actual); } struct ActualFunction : public Actual> @@ -345,6 +361,14 @@ void exists() const; void not_exists() const; + void startswith(const std::string& data) const; + void empty() const; + void not_empty() const; + void contents_equal(const std::string& data) const; + void contents_equal(const std::vector& data) const; + void contents_equal(const std::initializer_list& lines) const; + void contents_match(const std::string& data_re) const; + void contents_match(const std::initializer_list& lines_re) const; }; inline ActualFile actual_file(const std::string& pathname) { return ActualFile(pathname); } @@ -373,6 +397,26 @@ #define wassert_false(...) wassert(actual(__VA_ARGS__).isfalse()) /** + * Ensure that the expression throws the given exception. + * + * Returns a copy of the exception, which can be used for further evaluation. + */ +#define wassert_throws(exc, ...) \ + [&]() { try { \ + __VA_ARGS__ ; \ + wfail_test(#__VA_ARGS__ " did not throw " #exc); \ + } catch (TestFailed& e) { \ + throw; \ + } catch (exc& e) { \ + return e; \ + } catch (std::exception& e) { \ + std::string msg(#__VA_ARGS__ " did not throw " #exc " but threw "); \ + msg += typeid(e).name(); \ + msg += " instead"; \ + wfail_test(msg); \ + } }() + +/** * Call a function returning its result, and raising TestFailed with the * appropriate backtrace information if it threw an exception. * @@ -389,223 +433,18 @@ throw wreport::tests::TestFailed(e, __FILE__, __LINE__, #func, wreport_test_location_info); \ } }() - -struct TestCase; - -/** - * Result of running a test method. - */ -struct TestMethodResult -{ - /// Name of the test case - std::string test_case; - - /// Name of the test method - std::string test_method; - - /// If non-empty, the test failed with this error - std::string error_message; - - /// Stack frame of where the error happened - TestStack error_stack; - - /// If non-empty, the test threw an exception and this is its type ID - std::string exception_typeid; - - /// True if the test has been skipped - bool skipped = false; - - - TestMethodResult(const std::string& test_case, const std::string& test_method) - : test_case(test_case), test_method(test_method) {} - - void set_failed(TestFailed& e) - { - error_message = e.what(); - error_stack = e.stack; - if (error_message.empty()) - error_message = "test failed with an empty error message"; - } - - void set_exception(std::exception& e) - { - error_message = e.what(); - if (error_message.empty()) - error_message = "test threw an exception with an empty error message"; - exception_typeid = typeid(e).name(); - } - - void set_unknown_exception() - { - error_message = "unknown exception caught"; - } - - void set_setup_exception(std::exception& e) - { - error_message = "[setup failed: "; - error_message += e.what(); - error_message += "]"; - } - - void set_teardown_exception(std::exception& e) - { - error_message = "[teardown failed: "; - error_message += e.what(); - error_message += "]"; - } - - bool is_success() const - { - return error_message.empty(); - } -}; - /** - * Result of running a whole test case + * Fail a test with an error message */ -struct TestCaseResult -{ - /// Name of the test case - std::string test_case; - /// Outcome of all the methods that have been run - std::vector methods; - /// Set to a non-empty string if the setup method of the test case failed - std::string fail_setup; - /// Set to a non-empty string if the teardown method of the test case - /// failed - std::string fail_teardown; - /// Set to true if this test case has been skipped - bool skipped = false; - - TestCaseResult(const std::string& test_case) : test_case(test_case) {} - - void set_setup_failed() - { - fail_setup = "test case setup method threw an unknown exception"; - } - - void set_setup_failed(std::exception& e) - { - fail_setup = "test case setup method threw an exception: "; - fail_setup += e.what(); - } - - void set_teardown_failed() - { - fail_teardown = "test case teardown method threw an unknown exception"; - } - - void set_teardown_failed(std::exception& e) - { - fail_teardown = "test case teardown method threw an exception: "; - fail_teardown += e.what(); - } - - void add_test_method(TestMethodResult&& e) - { - methods.emplace_back(std::move(e)); - } - - bool is_success() const - { - if (!fail_setup.empty() || !fail_teardown.empty()) return false; - for (const auto& m: methods) - if (!m.is_success()) - return false; - return true; - } -}; +#define wfail_test(msg) wassert(throw wreport::tests::TestFailed((msg))) struct TestCase; +struct TestController; +struct TestRegistry; struct TestCaseResult; struct TestMethod; struct TestMethodResult; -/** - * Abstract interface for the objects that supervise test execution. - * - * This can be used for printing progress, or to skip test methods or test - * cases. - */ -struct TestController -{ - virtual ~TestController() {} - - /** - * Called before running a test case. - * - * @returns true if the test case should be run, false if it should be skipped - */ - virtual bool test_case_begin(const TestCase& test_case, const TestCaseResult& test_case_result) { return true; } - - /** - * Called after running a test case. - */ - virtual void test_case_end(const TestCase& test_case, const TestCaseResult& test_case_result) {} - - /** - * Called before running a test method. - * - * @returns true if the test method should be run, false if it should be skipped - */ - virtual bool test_method_begin(const TestMethod& test_method, const TestMethodResult& test_method_result) { return true; } - - /** - * Called after running a test method. - */ - virtual void test_method_end(const TestMethod& test_method, const TestMethodResult& test_method_result) {} -}; - -/** - * Simple default implementation of TestController. - * - * It does progress printing to stdout and basic glob-based test method - * filtering. - */ -struct SimpleTestController : public TestController -{ - /// Any method not matching this glob expression will not be run - std::string whitelist; - - /// Any method matching this glob expression will not be run - std::string blacklist; - - bool test_case_begin(const TestCase& test_case, const TestCaseResult& test_case_result) override; - void test_case_end(const TestCase& test_case, const TestCaseResult& test_case_result) override; - bool test_method_begin(const TestMethod& test_method, const TestMethodResult& test_method_result) override; - void test_method_end(const TestMethod& test_method, const TestMethodResult& test_method_result) override; - - bool test_method_should_run(const std::string& fullname) const; -}; - - -/** - * Test registry. - * - * It collects information about all known test cases and takes care of running - * them. - */ -struct TestRegistry -{ - /// All known test cases - std::vector entries; - - /** - * Register a new test case. - * - * No memory management is done: test_case needs to exist for the whole - * lifetime of TestRegistry. - */ - void register_test_case(TestCase& test_case); - - /** - * Run all the registered tests using the given controller - */ - std::vector run_tests(TestController& controller); - - /// Get the singleton instance of TestRegistry - static TestRegistry& get(); -}; /** * Test method information @@ -615,9 +454,19 @@ /// Name of the test method std::string name; - /// Main body of the test method + /// Documentation attached to this test method + std::string doc; + + /** + * Main body of the test method. + * + * If nullptr, the test will be skipped. + */ std::function test_function; + TestMethod(const std::string& name) + : name(name) {} + TestMethod(const std::string& name, std::function test_function) : name(name), test_function(test_function) {} }; @@ -635,14 +484,19 @@ /// All registered test methods std::vector methods; - TestCase(const std::string& name) - : name(name) - { - TestRegistry::get().register_test_case(*this); - } + /// Set to true the first time register_tests_once is run + bool tests_registered = false; + + + TestCase(const std::string& name); virtual ~TestCase() {} /** + * Idempotent wrapper for register_tests() + */ + void register_tests_once(); + + /** * This will be called before running the test case, to populate it with * its test methods. * @@ -695,33 +549,34 @@ virtual TestMethodResult run_test(TestController& controller, TestMethod& method); /** - * Register a new test method + * Register a new test method, with the actual test function to be added + * later */ - template - void add_method(const std::string& name, std::function test_function) + TestMethod& add_method(const std::string& name) { - methods.emplace_back(name, test_function); + methods.emplace_back(name); + return methods.back(); } /** * Register a new test method */ template - void add_method(const std::string& name, std::function test_function, Args&&... args) + TestMethod& add_method(const std::string& name, std::function test_function) { - methods.emplace_back(name, test_function, std::forward(args)...); + methods.emplace_back(name, test_function); + return methods.back(); } /** - * Register a new test metheod, with arguments. - * - * Any extra arguments to the function will be passed to the test method. + * Register a new test method, including documentation */ - template - void add_method(const std::string& name, FUNC test_function, Args&&... args) + template + TestMethod& add_method(const std::string& name, const std::string& doc, std::function test_function) { - auto f = std::bind(test_function, args...); - methods.emplace_back(name, f); + methods.emplace_back(name, test_function); + methods.back().doc = doc; + return methods.back(); } }; @@ -796,33 +651,26 @@ } /** - * Add a method that takes a reference to the fixture as argument. - * - * Any extra arguments to the function will be passed to the test method - * after the fixture. + * Register a new test method that takes a reference to the fixture as + * argument. */ - template - void add_method(const std::string& name, FUNC test_function) + template + TestMethod& add_method(const std::string& name, std::function test_function) { - methods.emplace_back(name, [=]() { - test_function(*fixture); - }); + return TestCase::add_method(name, [=]() { test_function(*fixture); }); } -}; -#if 0 - struct Test + /** + * Register a new test method that takes a reference to the fixture as + * argument, including documentation + */ + template + TestMethod& add_method(const std::string& name, const std::string& doc, std::function test_function) { - std::string name; - std::function test_func; - }; - - /// Add tests to the test case - virtual void add_tests() {} -#endif - + return TestCase::add_method(name, doc, [=]() { test_function(*fixture); }); + } +}; } } - #endif diff -Nru wreport-3.6/wreport/utils/tests-main.cc wreport-3.15/wreport/utils/tests-main.cc --- wreport-3.6/wreport/utils/tests-main.cc 2016-08-18 13:09:53.000000000 +0000 +++ wreport-3.15/wreport/utils/tests-main.cc 2018-05-12 13:35:35.000000000 +0000 @@ -1,4 +1,6 @@ #include "tests.h" +#include "testrunner.h" +#include "term.h" #include #include #include @@ -16,124 +18,29 @@ signal(SIGSEGV, signal_to_exception); signal(SIGILL, signal_to_exception); -#if 0 - if( (argc == 2 && (! strcmp ("help", argv[1]))) || argc > 3 ) - { - std::cout << "TUT example test application." << std::endl; - std::cout << "Usage: example [regression] | [list] | [ group] [test]" << std::endl; - std::cout << " List all groups: example list" << std::endl; - std::cout << " Run all tests: example regression" << std::endl; - std::cout << " Run one group: example std::auto_ptr" << std::endl; - std::cout << " Run one test: example std::auto_ptr 3" << std::endl;; - } - - // std::cout << "\nFAILURE and EXCEPTION in these tests are FAKE ;)\n\n"; - - tut::runner.get().set_callback(&visi); - - try - { - if( argc == 1 || (argc == 2 && std::string(argv[1]) == "regression") ) - { - tut::runner.get().run_tests(); - } - else if( argc == 2 && std::string(argv[1]) == "list" ) - { - std::cout << "registered test groups:" << std::endl; - tut::groupnames gl = tut::runner.get().list_groups(); - tut::groupnames::const_iterator i = gl.begin(); - tut::groupnames::const_iterator e = gl.end(); - while( i != e ) - { - std::cout << " " << *i << std::endl; - ++i; - } - } - else if( argc == 2 && std::string(argv[1]) != "regression" ) - { - tut::runner.get().run_tests(argv[1]); - } - else if( argc == 3 ) - { - tut::runner.get().run_test(argv[1],::atoi(argv[2])); - } - } - catch( const std::exception& ex ) - { - std::cerr << "tut raised exception: " << ex.what() << std::endl; - } -#endif - auto& tests = TestRegistry::get(); - SimpleTestController controller; + wreport::term::Terminal output(stderr); - if (const char* whitelist = getenv("TEST_WHITELIST")) - controller.whitelist = whitelist; + std::unique_ptr controller; - if (const char* blacklist = getenv("TEST_BLACKLIST")) - controller.blacklist = blacklist; + bool verbose = (bool)getenv("TEST_VERBOSE"); - auto all_results = tests.run_tests(controller); + if (verbose) + controller.reset(new VerboseTestController(output)); + else + controller.reset(new SimpleTestController(output)); - unsigned methods_ok = 0; - unsigned methods_failed = 0; - unsigned methods_skipped = 0; - unsigned test_cases_ok = 0; - unsigned test_cases_failed = 0; - - for (const auto& tc_res: all_results) - { - if (!tc_res.fail_setup.empty()) - { - fprintf(stderr, "%s: %s\n", tc_res.test_case.c_str(), tc_res.fail_setup.c_str()); - ++test_cases_failed; - } else { - if (!tc_res.fail_teardown.empty()) - { - fprintf(stderr, "%s: %s\n", tc_res.test_case.c_str(), tc_res.fail_teardown.c_str()); - ++test_cases_failed; - } - else - ++test_cases_ok; - - for (const auto& tm_res: tc_res.methods) - { - if (tm_res.skipped) - ++methods_skipped; - else if (tm_res.is_success()) - ++methods_ok; - else - { - fprintf(stderr, "\n"); - if (tm_res.exception_typeid.empty()) - fprintf(stderr, "%s.%s: %s\n", tm_res.test_case.c_str(), tm_res.test_method.c_str(), tm_res.error_message.c_str()); - else - fprintf(stderr, "%s.%s:[%s] %s\n", tm_res.test_case.c_str(), tm_res.test_method.c_str(), tm_res.exception_typeid.c_str(), tm_res.error_message.c_str()); - for (const auto& frame : tm_res.error_stack) - fprintf(stderr, " %s", frame.format().c_str()); - ++methods_failed; - } - } - } - } - - bool success = true; - - if (test_cases_failed) - { - success = false; - fprintf(stderr, "\n%u/%u test cases had issues initializing or cleaning up\n", - test_cases_failed, test_cases_ok + test_cases_failed); - } - - if (methods_failed) - { - success = false; - fprintf(stderr, "\n%u/%u tests failed\n", methods_failed, methods_ok + methods_failed); - } - else - fprintf(stderr, "%u tests succeeded\n", methods_ok); + if (const char* whitelist = getenv("TEST_WHITELIST")) + controller->whitelist = whitelist; + + if (const char* blacklist = getenv("TEST_BLACKLIST")) + controller->blacklist = blacklist; - return success ? 0 : 1; + auto all_results = tests.run_tests(*controller); + TestResultStats rstats(all_results); + rstats.print_results(output); + if (verbose) rstats.print_stats(output); + rstats.print_summary(output); + return rstats.success ? 0 : 1; } diff -Nru wreport-3.6/wreport/var.cc wreport-3.15/wreport/var.cc --- wreport-3.6/wreport/var.cc 2016-08-18 13:30:03.000000000 +0000 +++ wreport-3.15/wreport/var.cc 2018-06-05 07:47:44.000000000 +0000 @@ -83,6 +83,15 @@ return val; } +bool isnumber(const char *str) +{ + if (*str == '-') ++str; + while (*str) + if (!isdigit(*str++)) + return false; + return true; +} + } namespace wreport { @@ -501,7 +510,9 @@ case Vartype::Binary: assign_b_checked((uint8_t*)val, m_info->len); break; case Vartype::Decimal: case Vartype::Integer: - if (*val == '-') + if (!isnumber(val)) + unset(); + else if (*val == '-') assign_i_checked(-str_to_unsigned(val + 1)); else assign_i_checked(str_to_unsigned(val)); @@ -532,7 +543,9 @@ case Vartype::Binary: assign_b_checked((uint8_t*)val.c_str(), val.size()); break; case Vartype::Integer: case Vartype::Decimal: - if (val[0] == '-') + if (!isnumber(val.c_str())) + unset(); + else if (val[0] == '-') assign_i_checked(-str_to_unsigned(val.c_str() + 1)); else assign_i_checked(str_to_unsigned(val.c_str())); diff -Nru wreport-3.6/wreport/varinfo.cc wreport-3.15/wreport/varinfo.cc --- wreport-3.6/wreport/varinfo.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/varinfo.cc 2018-09-19 10:47:52.000000000 +0000 @@ -97,8 +97,8 @@ int bit_ref, int bit_len) { this->code = code; - strncpy(this->desc, desc, 64); - strncpy(this->unit, unit, 24); + strncpy(this->desc, desc, 63); this->desc[63] = 0; + strncpy(this->unit, unit, 23); this->desc[23] = 0; this->scale = scale; this->len = len; this->bit_ref = bit_ref; @@ -118,8 +118,8 @@ int scale, unsigned len) { this->code = code; - strncpy(this->desc, desc, 64); - strncpy(this->unit, unit, 24); + strncpy(this->desc, desc, 63); this->desc[63] = 0; + strncpy(this->unit, unit, 23); this->desc[23] = 0; this->scale = scale; this->len = len; this->bit_ref = 0; @@ -136,7 +136,7 @@ void _Varinfo::set_string(Varcode code, const char* desc, unsigned len) { this->code = code; - strncpy(this->desc, desc, 64); + strncpy(this->desc, desc, 63); this->desc[63] = 0; strncpy(this->unit, "CCITTIA5", 24); this->scale = 0; this->len = len; @@ -149,7 +149,7 @@ void _Varinfo::set_binary(Varcode code, const char* desc, unsigned bit_len) { this->code = code; - strncpy(this->desc, desc, 64); + strncpy(this->desc, desc, 63); this->desc[63] = 0; strncpy(this->unit, "UNKNOWN", 24); this->scale = 0; this->len = ceil(bit_len / 8.0); diff -Nru wreport-3.6/wreport/var-test.cc wreport-3.15/wreport/var-test.cc --- wreport-3.6/wreport/var-test.cc 2015-10-12 12:05:16.000000000 +0000 +++ wreport-3.15/wreport/var-test.cc 2018-06-05 07:47:44.000000000 +0000 @@ -392,6 +392,15 @@ Var var3(move(var2)); wassert(actual(var3.enqc()) == "ciaon"); }); + add_method("issue17", []() { + _Varinfo vi; + vi.set_bufr(WR_VAR(0, 0, 0), "TEST", "?", 2, 5, 0, 16); + Var var(&vi); + wassert(var.sets("None")); + wassert_false(var.isset()); + wassert(var.setc("None")); + wassert_false(var.isset()); + }); } #if 0