dballe-7.7/0000755000175000017500000000000012653425053007620 500000000000000dballe-7.7/missing0000755000175000017500000001533012652630066011142 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: dballe-7.7/README0000644000175000017500000001447412652630043010426 00000000000000DB-All.e =============================================================== Introduction ------------ DB-All.e is a fast on-disk database where meteorological observed and forecast data can be stored, searched, retrieved and updated. This framework allows to manage large amounts of data using its simple Application Program Interface, and provides tools to visualise, import and export in the standard formats BUFR, AOF and CREX. The main characteristics of DB-ALL.e are: * Fortran, C, C++ and Python APIs are provided. * To make computation easier, data is stored as physical quantities, that is, as measures of a variable in a specific point of space and time, rather than as a sequence of report. * Internal representation is similar to BUFR and CREX WMO standard (table code driven) and utility for import and export are included (generic and ECMWF template). * Representation is in 7 dimensions: latitude and longitude geographic coordinates, table driven vertical coordinate, reference time, table driven observation and forecast specification, table driven data type. * It allows to store extra information linked to the data, such as confidence intervals for quality control. * It allows to store extra information linked to the stations. * Variables can be represented as real, integer and characters, with appropriate precision for the type of measured value. * It is based on physical principles, that is, the data it contains are defined in terms of homogeneous and consistent physical data. For example, it is impossible for two incompatible values to exist in the same point in space and time. * It can manage fixed stations and moving stations such as airplanes or ships. * It can manage both observational and forecast data. * It can manage data along all three dimensions in space, such as data from soundings and airplanes. * Report information is preserved. It can work based on physical parameters or on report types. * It is temporary, to be used for a limited time and then be deleted. * Does not need backup, since it only contains replicated or derived data. * Write access is enabled for its users. Dependencies ------------ DB-All.e requires unixodbc, gperf and popt in order to be built. Additionally, to build the Fortran API the CNF library is required, and gfortran is required to build its unit tests. To build the documentation, you need doxygen and LaTeX. If latex2html is present, HTML documentation will also be built. If rst2html is present, the README file will also be converted to HTML. In Fedora, the names of the packages depended on are: * unixODBC-devel gperf gcc-gfortran doxygen tetex tetex-latex latex2html * For CNF there is an unofficial starmet package: contact the DB-All.e team about it. In Debian, the names of the packages depended on are: * unixodbc-dev gperf libpopt-dev libcnf-dev gfortran doxygen python-docutils * tetex-bin tetex-extra (in etch), or * texlive-base texlive-latex-base texlive-latex-extra texlive-latex-recommended (in lenny and sid) * latex2html (optional, from non-free) (see http://www.arpa.emr.it/dettaglio_documento.asp?id=514&idlivello=64) Building DB-All.e ----------------- DB-All.e is already packaged in both .rpm and .deb formats, and that provides easy installation for most Linux distributions. If you want to build and install DB-All.e yourself, you'll need to install the automake/autoconf/libtool packages then you can proceed as in most other Unix software: autoreconf -if ./configure make make install Getting started --------------- DB-All.e requires ODBC access to a MySQL database for most of its functionality. To set up DB-All.e on the MySQL side, you need to create a database and grant users create table, drop table, insert, delete and select access. MySQL needs to run with InnoDB support. To set up ODBC access to the database (this is called a DSN) you can run a graphical configuration file like ODBCConfig. Otherwise, this is a sample .odbc.ini you can use:: [dballe] Description = MySQL Driver = MySQL Server = localhost Database = dballe Once this is set up, you can initialise the DB-All.e database using the command:: dbadb wipe --dsn=dballe --user=username [--pass=password] "--user" can be omitted if it is the same as your Unix username; "--pass" can be omitted if the user has no password. If you do not already have access to datasets to import, some are available from http://www.ncar.ucar.edu/tools/datasets/ after registering (for free) on the website. Documentation ------------- Documentation for all commandline tools can be found in their manpages. All commandline tools also have extensive commandline help that can be accessed using the "--help" option. The Fortran API is documented in the fapi.pdf document. The C API and all the C internals are documented through Doxygen. Administration and maintanance of DB-All.e are covered in the guide.pdf document. Testing DB-All.e ---------------- Unit testing can be run using "make check", but it requires an existing DSN connection to a MySQL database, which should be called 'test'. Please note that unit testing functions will wipe existing DB-All.e tables on the test DSN database. Useful resources ---------------- ODBC links: * http://www.unixodbc.org/doc/ProgrammerManual/Tutorial/ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcabout_this_manual.asp BUFR decoding: * http://www.knmi.nl/~meulenvd/code/bufr/dmtn1.html AOF decoding: * Reading of Fortran "unformatted sequential" from C/C++: http://astronomy.swin.edu.au/~pbourke/dataformats/fortran/ ECWMF BUFR template codes: * http://www.ecmwf.int/research/ifsdocs/OBSERVATIONS/Chap2_Obs_types3.html Contact and copyright information --------------------------------- The author of DB-ALLe is Enrico Zini DB-ALLe is Copyright (C) 2005-2015 ARPA-SIMC DB-ALLe is licensed under the terms of the GNU General Public License version 2. Please see the file COPYING for details. Contact informations for ARPA-SIM: Agenzia Regionale Prevenzione e Ambiente (ARPA) Servizio Idro-Meteo-Climatologico (SIMC) Address: Viale Silvani 6, 40122 Bologna, Italy Tel: + 39 051 6497511 Fax: + 39 051 6497501 Email: urpsim@arpa.emr.it Website: http://www.arpa.emr.it/sim/ dballe-7.7/show_code_notes0000755000175000017500000000006312652630043012643 00000000000000#!/bin/sh find . | xargs grep 'FIXME\|TODO' | less dballe-7.7/ltmain.sh0000644000175000017500000105203012652630055011360 00000000000000 # libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.11 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.2 Debian-2.4.2-1.11" TIMESTAMP="" package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" func_resolve_sysroot "$deplib" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 dballe-7.7/tables/0000755000175000017500000000000012653425047011075 500000000000000dballe-7.7/tables/D0000000000200014001.txt0000644000175000017500000025404012652630043013567 00000000000000 300002 2 000002 000003 300003 3 000010 000011 000012 300004 9 300003 000013 000014 000015 000016 000017 000018 000019 000020 300010 4 300003 101000 031001 000030 301001 2 001001 001002 301002 3 001003 001004 001005 301003 3 001011 001012 001013 301004 4 001001 001002 001015 002001 301005 2 001035 001034 301011 3 004001 004002 004003 301012 2 004004 004005 301013 3 004004 004005 004006 301014 3 102002 301011 301012 301021 2 005001 006001 301022 3 005001 006001 007001 301023 2 005002 006002 301024 3 005002 006002 007001 301025 3 301023 004003 301012 301026 7 301021 004003 004003 004004 004004 004005 004005 301027 5 008007 101000 031001 301028 008007 301028 8 008040 033042 007010 101000 031002 301023 019007 008040 301031 5 301001 002001 301011 301012 301022 301032 5 301001 002001 301011 301012 301024 301033 5 001005 002001 301011 301012 301021 301034 5 001005 002001 301011 301012 301023 301035 7 001005 001012 001013 002001 301011 301012 301023 301036 5 301003 002001 301011 301012 301023 301037 6 301001 002011 002012 301011 301012 301022 301038 6 301001 002011 002012 301011 301012 301024 301039 6 301003 002011 002012 301011 301012 301023 301040 6 301003 002011 002012 301011 301012 301024 301041 5 001007 002021 002022 301011 301012 301042 2 301041 301021 301043 5 001007 002023 301011 301013 301021 301044 5 001007 002024 301011 301013 301021 301045 9 301011 301012 201138 202131 004006 201000 202000 304030 304031 301046 10 001007 001012 002048 021119 025060 202124 002026 002027 202000 005040 301047 15 001007 025060 001033 001034 001012 301045 002021 301011 301012 201138 202131 004006 201000 202000 301023 301048 14 002104 002121 002113 002026 002027 002111 002140 202127 001013 202126 007001 202000 025010 021064 301049 5 002111 002112 021062 021063 021065 301051 6 001006 002061 301011 301012 301021 008004 301055 7 001005 002001 301011 301012 301021 001012 001014 301062 3 101000 031001 301001 301065 8 001006 001008 002001 002002 002005 002062 002070 002065 301066 6 301011 301013 301023 007004 002064 008004 301070 3 002143 002142 002144 301071 5 001007 001031 002020 002028 002029 301072 4 301071 301011 301013 301021 301074 4 002143 002142 002145 002146 301075 6 301001 001015 301024 008021 301011 301012 301076 3 002011 002143 002142 301090 6 301004 301011 301012 301021 007030 007031 301091 10 002180 002181 002182 002183 002184 002179 002186 002187 002188 002189 301092 9 001011 001003 002001 301011 301012 301021 007030 007031 033024 301093 3 301036 007030 007031 301110 5 301001 001011 002011 002014 002003 301111 6 301001 001011 002011 002013 002014 002003 301112 5 001006 002011 002013 002014 002003 301113 3 008021 301011 301013 301114 5 301021 007030 007031 007007 033024 301120 4 301001 001094 002011 301121 301121 5 008041 301122 301021 007031 007007 301122 7 301011 301012 201135 202130 004006 202000 201000 301123 33 102002 008041 001062 301001 001094 002011 001018 001095 025061 025068 001082 001083 001081 002067 002066 002014 025067 025065 025066 002095 002096 002097 002016 002083 002080 002081 001093 002084 002085 002086 002082 008041 301011 301125 6 001033 001034 025060 001007 002019 001012 301193 5 001007 001031 002196 002221 002222 301194 9 001194 001012 001013 002011 002012 301011 301012 301023 007001 301195 9 001195 001012 001013 002011 002012 301011 301012 301023 007001 301196 7 301003 002011 002012 301011 301012 301023 007001 301197 9 001006 001008 002061 002062 002002 002005 002070 002063 002001 301198 9 001011 001012 001013 002011 002012 301011 301012 301023 007001 301200 2 001032 033194 301201 2 101003 033193 301202 2 001031 001032 301237 12 001007 001012 002021 301011 004004 004005 201138 202131 004006 201000 202000 301023 301238 14 002104 002121 002113 002026 002027 002111 002192 202127 001013 202126 007001 202000 025010 021194 301239 5 002111 002112 021192 021193 021195 301240 5 201131 202129 022021 201000 202000 301241 5 201141 202130 007001 201000 202000 301242 6 021207 021208 021209 021210 021211 021212 301250 4 301193 301011 301013 301021 302001 4 010004 010051 010061 010063 302002 5 010004 007004 010003 010061 010063 302003 9 011011 011012 012004 012006 013003 020001 020003 020004 020005 302004 7 020010 008002 020011 020013 020012 020012 020012 302005 4 008002 020011 020012 020013 302006 4 010004 010051 010062 010063 302011 3 302001 302003 302004 302012 3 302002 302003 302004 302013 5 302006 302003 101000 031001 302005 302021 3 022001 022011 022021 302022 3 022002 022012 022022 302023 3 022003 022013 022023 302024 3 302022 101002 302023 302031 4 302001 010062 007004 010009 302032 4 007032 012101 012103 013003 302033 2 007032 020001 302034 2 007032 013023 302035 8 302032 302033 302034 007032 302004 101000 031001 302005 302036 7 105000 031001 008002 020011 020012 020014 020017 302037 3 020062 013013 012113 302038 4 020003 004024 020004 020005 302039 2 004024 014031 302040 4 007032 102002 004024 013011 302041 7 007032 004024 004024 012111 004024 004024 012112 302042 11 007032 002002 008021 004025 011001 011002 008021 103002 004025 011043 011041 302043 7 302038 101002 302039 302040 302041 302042 007032 302044 3 004024 002004 013033 302045 7 004024 014002 014004 014016 014028 014029 014030 302046 3 004024 004024 012049 302047 3 102003 008002 020054 302048 5 005021 007021 020012 005021 007021 302049 7 008002 020011 020013 020012 020012 020012 008002 302050 31 008041 005021 007005 202130 006021 202000 008041 201131 202129 002115 010004 002115 013003 202000 201000 002115 011001 011002 002115 102002 012101 004024 002115 012103 012102 101003 020012 020011 020013 101002 020003 302051 12 010004 010051 007004 010003 012004 012051 012016 012017 013004 102004 008051 008020 302052 7 007032 007033 012101 002039 012102 012103 013003 302053 3 007032 007033 020001 302054 9 302052 302053 007033 302034 007032 302004 101000 031001 302005 302055 8 020031 020032 020033 020034 020035 020036 020037 020038 302056 4 002038 007063 022043 007063 302057 3 302056 302021 302024 302058 8 007032 007033 004024 004024 012111 004024 004024 012112 302059 12 007032 007033 002002 008021 004025 011001 011002 008021 103002 004025 011043 011041 302060 4 302038 302040 302058 302059 302062 24 302001 302052 302053 007033 101000 031000 302034 007032 101000 031001 302005 008002 101000 031000 302055 101000 031000 302056 101000 031000 302021 101000 031000 302024 302063 8 302038 101000 031000 302040 101000 031000 302058 302059 302066 16 020023 020024 020027 020054 020023 020027 020054 020025 020026 020027 020040 020066 020027 020021 020067 020027 302069 4 007032 007033 033041 020001 302070 8 007032 007033 011001 011002 011043 011041 011016 011017 302071 14 007032 007033 008021 004025 011001 011002 008021 103002 004025 011043 011041 004025 011016 011017 302072 5 007032 007033 012101 012103 013003 302073 7 020010 105004 008002 020011 020012 033041 020013 302074 4 020003 004025 020004 020005 302075 5 008021 004025 013055 013058 008021 302076 7 020021 020022 026020 020023 020024 020025 020026 302077 8 007032 007033 004025 012111 012112 007032 004025 012112 302078 4 002176 020062 002177 013013 302079 5 007032 002175 002178 004025 013011 302080 3 002185 004025 013033 302081 2 004025 014031 302082 7 004025 014002 014004 014016 014028 014029 014030 302083 8 004025 008023 010004 011001 011002 012101 013003 008023 302205 5 201131 202129 022021 201000 202000 302206 9 302205 201130 202129 022011 201000 202000 022001 011001 011002 302207 5 022193 022194 022195 022196 022197 302250 5 102000 031001 020193 020194 020012 303001 3 007003 011001 011002 303002 3 007004 011001 011002 303003 4 007004 010003 012001 012003 303004 6 007004 010003 012001 012003 011001 011002 303011 4 007003 008001 011001 011002 303012 4 007004 008001 011001 011002 303013 7 007004 008001 010003 012001 013003 011001 011002 303014 7 007004 008001 010003 012001 012003 011001 011002 303021 4 007004 007004 204007 031021 303022 3 303021 010003 204000 303023 3 303021 012001 204000 303024 3 303021 013016 204000 303025 5 002025 204007 031021 012063 204000 303026 6 007004 008003 204007 031021 012001 204000 303027 5 007004 204007 031021 010003 204000 303031 6 007004 008003 007021 007022 008012 012061 303032 2 020011 020016 303033 2 020010 020016 303040 18 008041 004025 004026 301021 301122 201131 202129 025069 007004 013003 202000 201000 002013 012101 010009 102002 008040 035035 303041 8 002152 002023 007004 011001 011002 002153 002154 012071 303050 7 004086 008042 007004 005015 006015 011001 011002 303051 7 004086 008042 007004 005015 006015 011061 011062 303052 7 004086 008042 007009 005015 006015 011001 011002 303053 7 004086 008042 007009 005015 006015 011061 011062 303054 10 004086 008042 007004 010009 005015 006015 012101 012103 011001 011002 303249 7 002252 104000 031001 002199 007004 007004 013003 303250 8 002252 002023 007004 011001 011002 002197 002198 012193 303251 8 002252 105000 031001 002254 002251 002197 002198 012063 303252 8 002252 105000 031001 002254 002251 002197 002198 012194 304001 5 008003 010004 012001 011001 011002 304002 4 008003 010004 011001 011002 304003 2 008003 012001 304004 4 008003 010004 020010 012001 304005 4 002024 007004 007004 013003 304006 3 014001 014001 014003 304011 27 002163 002164 008012 007024 002057 008021 004001 004002 004003 004004 008021 004024 110004 008021 004004 004005 004006 008021 004004 004005 004006 011001 011002 103010 002163 007004 012001 304030 3 027031 028031 010031 304031 3 001041 001042 001043 304032 5 002153 002154 020081 020082 020012 304033 8 002152 002166 002167 002153 002154 012075 012076 012063 304034 9 102004 027001 028001 007022 005043 020010 020016 033003 010040 304035 15 002153 002154 012063 008001 012063 008001 012063 008001 008003 012063 008003 012063 008003 012063 008003 304036 12 020082 008012 020082 008012 020081 008003 020081 008003 020081 008003 020081 008003 304228 3 005217 006217 007217 304229 3 001208 001209 001210 304250 27 002231 002232 008012 007024 002057 008021 004001 004002 004003 004004 008021 004024 110004 008021 004004 004005 004006 008021 004004 004005 004006 011001 011002 103010 002231 007004 012001 305003 5 301012 004065 101000 031001 305001 305006 6 013072 013082 013019 012001 013073 013060 305007 6 301029 301012 004065 101000 031001 305006 305008 2 305006 012030 305009 6 301029 301012 004065 101000 031001 305008 305011 6 301029 301012 004065 101000 031001 305010 305018 8 301029 301012 004065 103000 031001 305008 305016 305017 306001 5 002032 102000 031001 007062 022042 306002 3 002031 022004 022031 306003 4 002002 011011 011012 012004 306004 7 002032 002033 103000 031001 007062 022043 022062 306005 6 002031 103000 031001 007062 022004 022031 306006 3 306003 306002 022063 306007 6 001012 001014 306008 004024 027003 028003 306008 3 002034 002035 002036 306019 8 001075 301011 301012 022042 022120 022121 004015 004065 306020 4 306024 102006 022038 022039 306021 7 001075 301011 301012 022122 022123 012001 303002 306022 5 001075 301011 301012 022038 022039 306023 8 001015 301023 301011 301012 022038 022039 022120 022121 306024 8 001075 301011 301012 022042 022120 022121 004025 004015 306025 4 306019 102006 022038 022039 307001 2 301031 302011 307002 2 301032 302011 307003 4 307001 101000 031001 302005 307004 4 307002 101000 031001 302005 307005 3 307001 101004 302005 307006 3 307002 101004 302005 307007 2 301031 302012 307008 2 301032 302012 307009 2 301031 302013 307011 16 001063 002001 301011 301012 301024 007006 011001 011016 011017 011002 011041 007006 012001 012003 010052 020009 307012 5 103000 031001 008023 005021 020001 307013 8 106000 031001 001064 008014 020061 008014 020061 020018 307014 3 101000 031001 020019 307015 4 101000 031001 302005 020002 307016 3 101000 031001 020020 307017 3 101000 031001 011070 307018 16 008016 102000 031001 008017 301012 104000 031001 007006 011001 011002 011041 020009 101000 031001 020001 307014 307020 3 307011 307014 307016 307021 9 307011 307012 307013 307014 307015 307016 307017 307018 307015 307022 31 001015 301011 301012 301022 008021 004025 010004 012001 013003 033038 008022 106025 002020 001050 005021 007021 015031 015032 008060 015033 015034 008060 015033 015034 015035 201131 202129 013016 202000 201000 015011 307030 2 015001 015002 307031 7 008022 008023 015001 008023 015001 008023 015002 307041 7 301001 001015 301022 301011 301012 301070 307030 307042 9 301001 001015 301022 301011 301012 008021 004025 301070 307031 307043 7 301001 001015 301024 301011 301012 301074 307030 307045 25 001063 008079 002001 301011 301012 301024 007032 011001 011016 011017 008054 011083 011084 011002 008054 011085 011086 011041 008054 007032 012023 012024 007032 010052 020009 307046 5 020060 Metar/speci visibility 102000 031001 005021 020059 307047 9 105000 Metar/speci clouds 031001 008002 020011 020012 020013 020092 020002 020091 307048 25 008016 102000 031001 008017 301012 112000 031000 007032 011001 008054 011083 011084 011002 008054 011085 011086 011041 008054 007032 020009 101000 031000 020060 307014 307047 307049 4 102000 031000 022043 022021 307050 14 101000 031000 020085 102000 031001 001064 020085 105000 031001 001064 020086 020087 020088 020089 307059 12 307045 Full METAR/SPECI 307046 307013 307014 307047 307016 307017 307049 307050 101000 031001 307048 Trend forecast 307052 12 001063 008039 301011 301012 008079 008039 301011 start of forecast 301012 008039 301011 end of forecast 301012 301024 307053 16 007032 011001 008054 011083 011084 011002 008054 011085 011086 011041 008054 007032 020009 020060 307014 307047 307054 13 007032 008039 004003 004004 008023 012023 008039 004003 004004 008023 012023 008023 007032 307055 9 033045 008016 008039 004003 301012 008039 004003 301012 307053 307056 6 307052 Aerodrome forecast 307053 307054 101000 031001 307055 307059 12 307045 Full METAR/SPECI 307046 307013 307014 307047 307016 307017 307049 307050 101000 031001 307048 Trend forecast 307060 2 007061 012030 307061 3 301031 101005 307060 307062 3 301032 101005 307060 307063 2 007061 012130 307071 67 301090 004074 004023 008023 010004 010051 007004 010009 007032 012101 002051 004051 012118 004052 012119 013004 008023 012151 007032 102005 008050 008020 014032 014033 008050 008020 102018 008052 008022 007032 008053 004003 012152 008053 004003 012153 008053 004003 008023 012101 008053 004003 008023 012101 008023 007032 002002 008053 004003 011046 008053 004003 004004 004023 007032 013060 013051 004053 008050 008020 102006 008052 008022 008053 004003 013052 007032 307072 38 004001 004001 004002 004003 004004 004074 004022 008023 010004 010051 007004 010009 007032 012101 002051 004051 012118 004052 012119 013004 012151 007032 014032 008023 004001 004001 004002 004003 004004 004022 007032 008023 013060 004053 008023 102008 008050 008020 307073 2 307071 307072 307079 30 301090 SYNOP data and marine data from costal stations 302031 302035 302036 101000 031000 302047 008002 101000 031000 302048 302037 102000 031000 022061 020058 101000 031000 302056 101000 031000 302055 302043 302044 101000 031001 302045 101000 031000 302046 307080 13 301090 BUFR template for synoptic reports 302031 302035 302036 302047 008002 302048 302037 302043 302044 101002 302045 302046 307081 24 301090 BUFR template for synoptic reports RA I 302031 302035 302036 302047 008002 302048 302037 012122 013056 013057 020101 020102 020103 020104 020105 020106 020107 020108 302043 302044 101002 302045 302046 307082 15 301090 BUFR template for synoptic reports RA II 302031 302035 302036 302047 008002 302048 302037 012121 012122 302043 302044 101002 302045 302046 307083 14 301090 BUFR template for synoptic reports RA III 302031 302035 302036 302047 008002 302048 302037 012122 302043 302044 101002 302045 302046 307084 17 301090 BUFR template for synoptic reports RA IV 302031 302035 302036 302047 008002 302048 302037 020055 101000 031000 205001 302043 302044 101002 302045 302046 307086 11 301090 BUFR template for synoptic reports RA VI 302031 302035 302036 008002 302037 302066 302043 302044 101002 302045 307090 13 301092 BUFR template for synoptic reports from mobile land stations 302031 302035 302036 302047 008002 302048 302037 302043 302044 101002 302045 302046 307091 66 301089 301090 008010 301091 302001 007004 010009 302072 103000 031000 101005 307063 007061 101000 031000 302069 007032 007033 105000 031000 020031 020032 002038 022043 302021 101000 031000 302078 101000 031000 302073 101000 031000 302074 101000 031000 302075 102000 031000 004025 302076 302071 302077 007033 101000 031000 302079 007032 101000 031000 302080 101000 031000 302081 101000 031000 302082 102000 031000 004025 013059 101000 031000 302083 033005 033006 307092 62 301089 Surface obs drom N-minute period 301090 008010 301091 004015 004065 125000 031001 010004 302070 302072 007032 012101 103000 031000 101005 307063 007061 101000 031000 302069 007032 007033 101000 031000 302073 101000 031000 302076 102000 031000 013055 013058 102000 031000 020031 020032 101000 031000 302078 102000 031000 302079 007032 101000 031000 302080 101000 031000 302081 101000 031000 302083 102000 031000 004025 013059 101000 031000 302083 033005 033006 308001 3 301033 302011 022042 308002 3 301034 302011 022042 308003 3 301035 302011 022042 308004 3 301036 302011 022042 308005 2 308004 302024 308006 8 010004 010061 010063 011001 011002 012004 013003 022042 308007 4 301055 302011 007062 022042 308008 84 001003 BUOY 001020 001005 002001 002036 002149 301011 301012 008021 301011 301012 008021 301021 027004 028004 007030 001051 002148 001012 001014 002040 033022 033023 033027 022063 302021 302022 302023 008081 025026 008081 025026 008081 025026 008081 002034 022060 007070 002190 025086 002035 002168 020031 002038 306004 002030 306005 007031 008081 012064 302001 008081 007032 007033 012101 012103 013003 007032 007033 008082 007033 002169 002002 008021 004025 011001 011002 008021 004025 011043 011041 008082 007033 007032 004024 013011 007032 008021 004024 014021 008021 025028 025028 025028 308009 7 301093 302001 302054 008002 302055 302057 302060 308010 16 001011 TRACKOB template 113000 031001 301011 301012 301021 004080 022049 004080 022059 004080 022005 002042 022032 002042 004080 308011 27 001011 Climat ship 002001 301011 301012 301023 007030 007031 004074 004023 008023 010051 007032 007033 012101 013004 007032 007033 302056 008023 004003 004004 004023 007032 013060 013051 004053 007032 308012 28 004001 Monthly normals from an ocean weather station 004001 004002 004003 004004 004074 004022 008023 010051 007032 007033 012101 013002 007032 007033 302056 008023 004001 004001 004002 004003 004004 004022 007032 008023 013060 004053 008023 308013 2 308011 308012 309001 4 301037 101000 031001 303011 309002 4 301038 101000 031001 303011 309003 4 301037 101000 031001 303012 309004 4 301038 101000 031001 303012 309005 5 301037 302004 101000 031001 303013 309006 5 301038 302004 101000 031001 303013 309007 5 301037 302004 101000 031001 303014 309008 5 301038 302004 101000 031001 303014 309011 4 301039 101000 031001 303011 309012 4 301039 101000 031001 303012 309013 5 301039 302004 101000 031001 303013 309014 5 301039 302004 101000 031001 303014 309015 4 301040 101000 031001 303011 309016 4 301040 101000 031001 303012 309017 5 301040 302004 101000 031001 303013 309018 5 301040 302004 101000 031001 303014 309019 5 301031 002003 101000 031001 303011 309020 8 301031 002003 104000 031001 007003 011003 011004 011005 309030 8 015004 015005 104000 031001 004015 008006 007004 015003 309031 8 015004 015005 104000 031001 004025 008006 007004 015003 309040 3 301075 301076 309030 309042 4 307042 301075 301076 309030 309050 9 301110 301113 301114 101000 031002 303050 101000 031001 303051 309051 9 301110 301113 301114 101000 031002 303052 101000 031001 303053 309052 11 301111 301113 301114 302049 022043 101000 031002 303054 101000 031001 303051 309053 9 301112 301113 301114 101000 031002 303054 101000 031001 303051 309054 27 301001 001011 301011 301012 301021 007030 007031 007007 004023 004059 115000 031001 008001 008023 007004 010009 012101 012103 008023 011001 011002 008023 011019 008050 008020 008050 008020 309060 4 301123 301121 302050 303040 309061 21 301120 008041 301122 201131 202129 025069 007004 202000 201000 033007 033035 033015 013009 033007 033035 033015 002013 012101 033007 033035 033015 309062 19 301120 008041 301122 005001 033035 033015 006001 033035 033015 007007 033035 033015 011003 033035 033015 011004 033035 033015 033007 309063 19 301120 008041 301122 005001 033035 033015 006001 033035 033015 007007 033035 033015 011003 033035 033015 011004 033035 033015 033007 309064 26 301120 008041 301122 201131 202129 104002 025069 007004 033035 033015 013003 033035 033015 202000 201000 104002 002013 012101 033035 033015 012103 033035 033015 010009 033035 033015 309065 18 301120 008041 301122 005001 033035 033015 006001 033035 033015 007007 033035 033015 011003 033035 033015 011004 033035 033015 309066 18 301120 008041 301122 008040 201131 202129 025069 007004 013003 202000 201000 002013 012101 012103 010009 010007 011002 011001 309194 5 301194 302004 101000 031001 303014 309195 5 301195 302004 101000 031001 303014 309196 5 301196 302004 101000 031001 303014 309198 5 301198 302004 101000 031001 303014 310001 5 301042 303031 303032 101026 303025 310002 5 301042 303031 303032 101009 303023 310003 5 301042 303031 303032 101006 303023 310004 5 301042 303031 303032 101003 303024 310005 6 301042 303031 303033 101000 031001 303025 310006 6 301042 303031 303033 101000 031001 303023 310007 6 301042 303031 303033 101000 031001 303024 310008 8 310011 101019 310012 002150 025079 025080 033032 014045 310009 3 310011 101015 310012 310010 3 310011 101005 310012 310011 45 008070 001033 001034 008070 001033 001034 001007 002048 005040 025075 201133 005041 201000 005043 025070 033030 033031 004001 004002 004003 004004 004005 202131 201138 004006 201000 202000 005001 006001 202126 007001 202000 007024 005021 007025 005022 033033 002151 012064 002151 012064 002151 012064 002151 012064 310012 10 002150 025076 025077 025078 033032 201132 202129 012063 202000 201000 310013 62 001007 005040 004001 004002 004003 004004 004005 004006 005001 006001 007025 005043 025085 201131 202129 002150 008023 008072 014027 008072 014027 002150 008023 008072 014027 008072 014027 002150 008023 008072 014027 008072 014027 202000 201000 201132 202129 002150 008023 008072 012063 008072 012063 002150 008023 008072 012063 008072 012063 008023 008072 012063 008072 012063 002150 008023 008072 012063 008072 012063 202000 201000 310014 3 301072 303041 304011 310015 13 301072 007024 010002 303041 101003 304032 002152 002024 007004 007004 013003 101003 304033 310016 13 301072 007024 010002 303041 101012 304032 002152 002024 007004 007004 013003 101012 304033 310019 68 001007 002019 301011 301013 301023 007025 008021 007025 008021 007025 008021 008029 005040 008075 008003 010004 008003 207002 015001 207000 033070 015030 207002 020081 207000 008003 033042 007004 207002 015001 207000 008003 113021 007004 007004 207002 008021 015005 008021 015005 033007 207000 008026 101020 025143 008026 008043 109015 007004 008090 207006 015008 207000 008090 207002 033007 207000 008043 033071 108008 202124 201107 002071 201000 202000 207002 020081 207000 310020 6 310022 301011 301013 301021 304034 310021 310021 10 108000 031001 201131 202129 007004 007004 202000 201000 015020 010002 310022 4 001007 002019 001033 002172 310023 17 301072 030021 030022 008012 007024 007025 010002 101012 304032 105002 002152 002024 007004 007004 013003 101012 304033 310024 17 301072 030021 030022 008012 007024 007025 010002 101003 304032 105002 002152 002024 007004 007004 013003 101003 304033 310025 61 001007 008021 004001 004002 004003 004004 004005 201138 202131 004006 202000 201000 201132 005041 201000 201129 005043 201000 005002 006002 013040 020029 104024 005042 012163 021083 021084 115003 004001 004002 004003 201142 202131 004026 202000 201000 005001 006001 201138 202129 007001 202000 201000 008021 004001 004002 004003 004004 004005 005040 101003 012070 025054 101004 025055 008007 104028 005002 006002 002111 005021 310026 82 310022 025060 008021 301011 301012 201138 202131 004006 202000 201000 033039 033007 304030 304031 002020 001050 202127 304030 202000 304031 201133 202131 004016 202000 201000 301021 304030 010035 005021 010036 113000 031002 301021 005021 108000 031001 002121 007040 015037 008023 201125 015037 201000 008023 033007 108000 031002 007007 015036 008023 201123 015036 201000 008023 033007 116000 031002 007009 010004 012001 013001 008023 201120 010004 201000 201122 012001 201000 201123 013001 201000 008023 033007 008003 007009 010004 008023 201120 010004 201000 008023 033007 310027 12 301071 301011 301013 301021 030021 030022 010002 304036 002152 002167 101011 304035 310029 12 110000 031001 201138 202130 007004 007004 202000 201000 015020 010002 012101 013098 310030 6 310022 301011 301013 301021 304034 310029 310050 14 310051 310052 101000 031002 310053 101004 310054 020010 310052 101015 310053 310052 101005 310053 310051 16 001007 005040 201133 005041 201000 201132 025070 201000 202126 007001 202000 007025 005022 102009 002151 012064 310052 12 002019 301011 301012 202131 201138 004006 201000 202000 301021 007024 005021 005043 310053 6 201134 005042 201000 025076 033032 012163 310054 13 201134 005042 201000 025076 033032 201131 202129 102002 008023 014027 008023 202000 201000 310055 8 310051 310052 102020 025076 025052 101000 031002 025050 310060 53 001007 001033 002019 002020 301011 301012 207003 004006 207000 304030 301021 007024 005021 007025 005022 008075 201133 005041 201000 005045 005043 005040 010001 201129 007002 201000 202127 201125 021166 201000 202000 008012 020010 020014 002165 033075 107003 008076 006029 006029 025140 025141 033076 033077 008076 033078 033003 104000 031002 201133 005042 201000 014044 310193 5 301250 303250 302250 303249 303251 310194 5 301250 303250 302250 303249 303252 310195 3 301250 303250 304250 310196 3 301250 303249 303251 310226 39 310022 025060 008021 301011 301012 201138 202131 004006 202000 201000 033039 033007 304030 304031 002020 001050 202127 304030 202000 304031 201133 202131 004016 202000 201000 301021 304030 010035 005021 010036 107000 031002 301021 005021 103000 031001 002121 007040 015037 311001 9 301051 007002 012001 011001 011002 011031 011032 011033 020041 311002 4 301065 301066 311003 311004 311003 5 010070 011001 011002 012001 013002 311004 18 101000 031000 011034 101000 031000 011035 101000 031000 011075 101000 031000 011076 101000 031000 033025 101000 031000 033026 311005 13 001008 001023 301021 301011 301013 007010 008009 011001 011002 011031 011036 012101 033025 311006 6 007010 011001 011002 002064 012101 012103 311007 7 007010 301021 011001 011002 002064 012101 012103 311008 8 001008 301011 301013 301021 008004 101000 031001 311006 311009 8 001008 301011 301013 301021 008004 101000 031001 311007 311193 16 301197 301011 301012 301023 008004 007004 008021 011001 011002 011031 011034 011035 012001 012003 013003 020041 312001 2 301043 304001 312002 2 301043 304002 312003 2 301042 304003 312004 2 301042 304004 312005 2 301042 020014 312006 2 301044 304005 312007 2 301042 304006 312010 6 001007 005040 002021 005041 004001 004043 312011 9 202131 201149 004006 201000 202126 010002 202000 005043 005053 312012 6 202129 201132 101019 012063 201000 202000 312013 6 005042 202129 201135 012063 201000 202000 312014 8 312010 312011 105056 301023 005042 005052 312012 312013 312015 10 109011 301023 005042 005052 202129 201132 101004 012063 202000 201000 312016 3 312010 312011 312015 312017 10 109008 301023 005042 005052 202129 201132 101003 012063 202000 201000 312018 3 312010 312011 312017 312019 13 301047 301048 015015 029002 021076 106012 201129 006030 201000 102012 005030 021075 021066 312020 11 301047 301048 015015 029002 021076 104012 006030 102012 005030 021075 021066 312021 6 301047 101003 301049 011012 011011 021067 312022 15 301047 008022 011012 011050 022070 022026 312041 010050 021068 021071 021072 021073 312042 021062 015011 312023 7 301047 103003 008022 012061 022050 021069 021085 312024 11 312020 008060 008022 008060 008022 025014 022101 022097 022098 022099 022100 312025 11 312019 008060 008022 008060 008022 025014 022101 022097 022098 022099 022100 312026 19 301046 301011 301013 301023 312031 101004 312030 021110 301023 321027 021111 301023 321027 021112 301023 321027 021113 301023 321027 312027 9 301047 105009 301023 007021 012061 007021 012061 021085 021070 312028 26 301046 301011 301013 301023 008025 201136 004006 201000 312031 312032 101004 312030 101002 312033 021110 301023 321028 021111 301023 321028 021112 301023 321028 021113 301023 321028 312030 13 201130 202129 011012 202000 201000 011052 201135 202130 011011 202000 201000 011053 021104 312031 8 005034 006034 021109 011081 011082 021101 021102 021103 312032 4 021120 021121 013055 021122 312033 4 002104 008022 012063 012065 312041 5 201141 202130 007001 201000 202000 312042 6 021077 021078 021079 021080 021081 021082 312045 21 001007 002019 001096 025061 005040 301011 301013 301021 007002 012180 012181 012182 012183 012184 012185 002174 021086 012186 021087 012187 033043 312050 23 001007 002019 001096 025061 005040 301011 301013 301021 007025 005022 010080 027080 008003 007004 013093 008003 201131 202129 007004 007004 202000 201000 013095 312051 48 001007 002019 001096 025061 005040 008075 301011 301013 301021 001012 201131 001013 201000 010032 010033 010034 007002 008012 025110 025111 025102 002104 025103 025104 025105 025106 025107 025108 002111 002121 002026 002027 021130 021131 021132 021133 021064 025014 021134 107018 005030 105024 201130 006030 201000 021135 021136 033044 312052 77 001007 002019 001096 025061 005040 025120 025121 025124 025125 025122 025123 301011 301013 301021 007002 002119 033047 010081 010082 010083 010084 002116 002117 002118 002156 002157 014055 022150 022151 022152 022153 022154 022155 022156 022157 022158 022159 021137 021138 021139 021140 021141 021142 010085 010086 010087 010088 010089 010090 010091 010092 010093 011002 025126 025127 025128 025129 025130 025131 025132 025133 025134 025135 025136 025137 013096 013097 011095 011096 012188 012189 002158 002159 033052 033053 021143 021144 312053 54 001007 002019 001096 025061 005040 008075 301011 301013 301021 001012 201131 001013 201000 010032 010033 010034 007002 008012 025110 025111 025102 002104 025103 025104 025105 025106 025107 025108 011001 011002 022160 025138 201130 202129 022021 202000 201000 033048 033049 002026 002027 021130 021131 021132 021133 025014 106036 005030 104024 201130 006030 201000 022161 033044 312055 5 005033 005040 006034 010095 021157 312056 11 025060 001032 011082 011081 020095 020096 021155 201133 021101 021102 201000 312057 12 201130 202129 011012 202000 201000 201131 202129 011011 202000 201000 021156 021104 312058 8 301125 301011 301013 301021 312055 021150 101003 321030 312059 4 312056 101000 031001 312057 312060 20 025060 025062 040001 040002 021062 021151 021152 021153 021154 021062 021062 040003 040004 040005 040006 040007 020065 040008 040009 040010 312061 3 312058 312060 312059 312070 27 001007 002019 001144 001124 030010 301011 301013 301021 007012 015012 012165 012166 012167 012168 027010 028010 002099 013048 025081 025082 025083 025084 012080 012081 012082 025174 033028 312200 10 301237 301238 029002 021206 104012 006232 102012 005232 021205 021196 312201 6 301237 101003 301239 011012 011011 021197 312202 13 301237 008022 011012 011050 301240 022243 301241 010050 021198 021201 021202 021203 301242 312203 8 301237 008022 012061 022050 021204 021199 021214 021215 312204 12 312201 001031 011012 011011 021200 021213 004004 008021 004024 055003 011012 011011 312207 3 312202 301202 033191 312208 17 301202 008022 008021 301011 301013 301023 302205 011002 001007 002021 301011 301013 301023 001032 001192 302205 011002 312209 11 301202 001192 301011 301013 301023 302206 104000 022192 102000 005232 022191 312210 13 312202 021192 015202 301011 004004 004005 201138 202131 004006 201000 202000 304228 304229 312211 19 301046 301011 301013 301023 312031 101004 312030 021110 101004 312212 021111 101004 312212 021112 101004 312212 021113 101004 312212 312212 2 301023 321027 313009 4 021001 101000 031001 021001 313010 4 021036 101000 031001 021036 313031 5 006002 006012 101000 031002 030001 313032 5 005002 005012 101000 031002 313031 313041 13 006002 110000 031001 104000 031001 006012 101000 031012 030001 006012 101000 031001 030001 313042 5 005002 005012 101000 031002 313041 313043 17 006002 005002 005012 112000 031001 110000 031001 104000 031001 006012 101000 031011 030001 006012 101000 031001 030001 315001 5 001011 301011 301012 301023 306001 315002 5 001011 301011 301012 301023 306004 315003 25 001087 001085 001086 002036 002148 002149 022055 022056 022067 301011 301012 301021 008080 033050 109000 031002 007065 008080 033050 022045 008080 033050 022064 008080 033050 316001 10 301011 004004 301023 001021 002041 019001 010051 019002 019003 019004 316002 15 008021 004001 004002 004003 004004 004005 001033 008021 004001 004002 004003 004004 004005 007002 007002 316003 12 110000 031001 008011 008007 104000 031001 005002 006002 010002 011002 008007 008011 316004 13 111000 031001 008011 008007 007002 007002 102000 031001 005002 006002 011031 008007 008011 316005 10 108000 031001 008005 008007 005002 006002 001026 019001 008007 008005 316006 14 112000 031001 008011 008007 007002 007002 102000 031001 005002 006002 020011 020012 008007 008011 316007 12 110000 031001 008011 008007 104000 031001 005002 006002 019005 019006 008007 008011 316008 13 111000 031001 008001 008007 008023 103000 031001 005002 006002 010002 008023 008007 008001 316009 13 111000 031001 008011 008007 007002 007002 102000 031001 005002 006002 020041 008007 008011 316010 9 107000 031001 008011 008007 001022 005002 006002 008007 008011 316011 19 117000 031001 008011 001022 008007 102000 031001 005002 006002 008021 004001 004002 004003 004004 004005 020090 008021 008007 008011 316020 5 001023 001025 001027 301011 301012 316021 23 301023 002041 019001 019007 019005 019006 019008 008005 010004 008005 010004 019007 008005 008021 004075 011040 019007 105004 005021 005021 102002 019003 019004 316022 24 001032 002041 019001 019010 118000 031001 008021 004014 008005 301023 019005 019006 010004 011041 008021 004075 011040 019008 105004 005021 005021 102002 019003 019004 316026 2 316020 316021 316030 10 301014 001037 010064 008019 001062 008019 001065 008019 001062 008019 316031 8 008021 301011 301012 301027 019005 019006 020028 008021 316032 5 008021 301011 301012 301027 008021 316033 7 008021 301011 301012 101000 031001 301027 008021 316034 17 008079 316030 008011 001022 008007 301023 008007 020090 316031 101000 031000 316032 101000 031001 316033 008011 008079 316035 9 008079 316030 008011 020023 020021 020008 316031 008011 008079 316036 13 008079 316030 008011 001027 316031 101000 031000 316032 101000 031001 316033 008011 008079 316037 7 008079 316030 008011 011031 316031 008011 008079 316038 8 008079 316030 008011 020041 020021 316031 008011 008079 316039 7 008079 316030 008011 020024 316031 008011 008079 316040 6 316030 008079 301014 001037 010064 008079 316050 16 301001 301011 301012 002160 008005 005002 006002 008005 019100 019005 019006 019101 019102 019103 019104 019105 316052 29 301005 301011 301012 001007 025150 122000 031001 001027 019150 019106 008005 005002 006002 008005 019107 019005 019006 019108 019109 019110 019111 019112 019113 019114 019115 019116 019117 019118 019119 318001 2 301025 024011 318003 4 301026 024005 024004 024021 318004 6 301025 004023 013011 024005 024004 024022 321001 6 002101 002114 002105 002106 002107 002121 321003 4 021051 021014 021017 021030 321004 5 301031 002003 101000 031001 321003 321005 12 025004 002121 002122 002123 002124 002125 002126 002127 002128 002129 002130 002131 321006 4 025001 025002 025003 025005 321007 8 025009 025010 025011 025012 025013 025015 025016 025017 321008 3 025006 025007 025008 321009 2 025018 025019 321010 13 002101 007002 002102 002103 002104 002105 002106 002107 002108 002109 002110 002132 002133 321011 3 030031 030032 029002 321012 3 101000 031001 002135 321021 15 002003 002101 201130 002106 201000 201132 202130 002121 202000 201000 201133 202129 025001 202000 201000 321022 11 007007 204001 031021 011001 204000 011002 204001 031021 011006 204000 021030 321023 9 007007 021091 021030 202129 021014 201129 021017 202000 201000 321024 7 007007 204001 031021 012007 011006 204000 021030 321025 17 007007 021091 021030 202129 021014 201129 021017 202000 201000 021092 021030 025092 201129 202129 021017 202000 201000 321026 10 007007 204001 031021 012007 025091 011071 011072 011073 011074 204000 321027 18 021118 202129 201132 002112 201000 201131 002111 201000 202000 002104 021105 021106 021107 021114 021115 021116 008018 021117 321028 18 021118 202129 201132 002112 201000 201131 002111 201000 202000 002104 021123 021106 021107 021114 021115 021116 008018 021117 321030 18 008085 202129 201131 002111 201000 202000 002134 021062 021063 021158 021159 021160 021161 021162 021163 021164 021165 021166 340001 45 001007 001031 002019 002020 004001 004002 004003 004004 004005 202131 201138 004006 201000 202000 005001 006001 007024 005021 007025 005022 005043 005040 201133 005041 201000 201132 025070 201000 202126 007001 202000 033060 033061 033062 033063 033064 033065 101010 340002 101087 340003 002019 025051 101007 340004 340002 3 025140 025141 025142 340003 5 104100 201136 005042 201000 014046 340004 9 005060 005061 025085 105006 005042 025142 014047 025142 014048 340005 94 001007 002019 001096 025061 005044 005040 001030 301011 301012 004007 005001 006001 008029 008074 008077 040011 025097 025095 025098 025099 021144 025096 040012 040013 021169 022151 022162 022163 025160 025133 022156 022164 022165 022166 021137 021138 022167 021139 021118 021145 021146 021147 022168 022169 022170 025161 025162 022171 022172 022173 022174 021170 021171 022175 021172 021118 021173 021174 021175 102003 002153 012063 013090 013091 007002 011097 011098 007002 011095 011096 010096 010081 010082 010083 010101 025132 025163 025126 025128 025164 010085 010097 010086 010087 010092 010088 010089 010098 010099 010090 010100 010093 025127 040014 340007 57 001007 001031 002019 002020 004001 004002 004003 004004 004005 202131 201138 004006 201000 202000 005001 006001 007024 005021 007025 005022 005043 005040 201133 005041 201000 201132 025070 201000 202126 007001 202000 103003 025140 025141 033060 033061 033062 033063 033064 033065 040020 101010 340002 101087 340003 002019 025051 101007 340004 020081 008029 020083 008029 040018 040019 040021 040022 340008 70 001007 001031 002019 002020 004001 004002 004003 004004 004005 202131 201138 004006 201000 202000 005001 006001 007024 005021 007025 005022 005043 005040 201133 005041 201000 201132 025070 201000 202126 007001 202000 103003 025140 025141 033060 033061 033062 033063 033064 033065 040020 101010 340002 104000 031002 201136 005042 201000 014046 108003 025140 025141 040015 040016 025062 101000 031002 040017 002019 025051 101007 340004 020081 008029 020083 008029 040018 040019 040021 040022 dballe-7.7/tables/Makefile.in0000644000175000017500000003742612652630066013074 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tables ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/m4_ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(tabledir)" 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) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FC = @FC@ FCFLAGS = @FCFLAGS@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDBALLEF_VERSION_INFO = @LIBDBALLEF_VERSION_INFO@ LIBDBALLE_VERSION_INFO = @LIBDBALLE_VERSION_INFO@ LIBOBJS = @LIBOBJS@ LIBPQ_CFLAGS = @LIBPQ_CFLAGS@ LIBPQ_LIBS = @LIBPQ_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ WREPORT_CFLAGS = @WREPORT_CFLAGS@ WREPORT_LIBS = @WREPORT_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_FC = @ac_ct_FC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_doxygen = @have_doxygen@ have_gperf = @have_gperf@ have_latex2html = @have_latex2html@ have_rst2html = @have_rst2html@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mysql_config = @mysql_config@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ tabledir = @tabledir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ crexbtables = B990203.txt B990204.txt B000299.txt crexdtables = D990203.txt D990204.txt D000299.txt bufrbtables = B000000002001200.txt \ B000000002001400.txt \ B0000000000200014001.txt bufrdtables = D000000002001200.txt \ D000000002001400.txt \ D0000000000200014001.txt table_DATA = repinfo.csv dballe.txt $(crexbtables) $(crexdtables) $(bufrbtables) $(bufrdtables) noinst_DATA = dballe.tex EXTRA_DIST = $(table_DATA) mkbdoc all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tables/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tables/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *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);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-tableDATA: $(table_DATA) @$(NORMAL_INSTALL) @list='$(table_DATA)'; test -n "$(tabledir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(tabledir)'"; \ $(MKDIR_P) "$(DESTDIR)$(tabledir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(tabledir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(tabledir)" || exit $$?; \ done uninstall-tableDATA: @$(NORMAL_UNINSTALL) @list='$(table_DATA)'; test -n "$(tabledir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(tabledir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(tabledir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-tableDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-tableDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distclean-local 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-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip install-tableDATA \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-tableDATA .PRECIOUS: Makefile dballe.tex: dballe.txt mkbdoc $(srcdir)/mkbdoc tex < $< > $@ B000000002001400.txt: dballe.txt cut -b 1-119 < $< > $@ B0000000000200014001.txt: dballe.txt cut -b 1-119 < $< > $@ B990204.txt: dballe.txt cp $< $@ B000299.txt: dballe.txt cp $< $@ distclean-local: rm -f dballe.tex # 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: dballe-7.7/tables/repinfo.csv0000644000175000017500000000056312652630043013171 0000000000000001,synop,synop,101,oss,0 02,metar,metar,81,oss,0 03,temp,sounding,98,oss,2 04,pilot,wind profile,80,oss,2 09,buoy,buoy,50,oss,31 10,ship,synop ship,99,oss,1 11,tempship,temp ship,100,oss,2 12,airep,airep,82,oss,4 13,amdar,amdar,97,oss,4 14,acars,acars,96,oss,4 42,pollution,pollution,199,oss,8 200,satellite,NOAA satellites,41,oss,255 255,generic,generic data,1000,?,255 dballe-7.7/tables/D000000002001400.txt0000644000175000017500000025404012652630043013266 00000000000000 300002 2 000002 000003 300003 3 000010 000011 000012 300004 9 300003 000013 000014 000015 000016 000017 000018 000019 000020 300010 4 300003 101000 031001 000030 301001 2 001001 001002 301002 3 001003 001004 001005 301003 3 001011 001012 001013 301004 4 001001 001002 001015 002001 301005 2 001035 001034 301011 3 004001 004002 004003 301012 2 004004 004005 301013 3 004004 004005 004006 301014 3 102002 301011 301012 301021 2 005001 006001 301022 3 005001 006001 007001 301023 2 005002 006002 301024 3 005002 006002 007001 301025 3 301023 004003 301012 301026 7 301021 004003 004003 004004 004004 004005 004005 301027 5 008007 101000 031001 301028 008007 301028 8 008040 033042 007010 101000 031002 301023 019007 008040 301031 5 301001 002001 301011 301012 301022 301032 5 301001 002001 301011 301012 301024 301033 5 001005 002001 301011 301012 301021 301034 5 001005 002001 301011 301012 301023 301035 7 001005 001012 001013 002001 301011 301012 301023 301036 5 301003 002001 301011 301012 301023 301037 6 301001 002011 002012 301011 301012 301022 301038 6 301001 002011 002012 301011 301012 301024 301039 6 301003 002011 002012 301011 301012 301023 301040 6 301003 002011 002012 301011 301012 301024 301041 5 001007 002021 002022 301011 301012 301042 2 301041 301021 301043 5 001007 002023 301011 301013 301021 301044 5 001007 002024 301011 301013 301021 301045 9 301011 301012 201138 202131 004006 201000 202000 304030 304031 301046 10 001007 001012 002048 021119 025060 202124 002026 002027 202000 005040 301047 15 001007 025060 001033 001034 001012 301045 002021 301011 301012 201138 202131 004006 201000 202000 301023 301048 14 002104 002121 002113 002026 002027 002111 002140 202127 001013 202126 007001 202000 025010 021064 301049 5 002111 002112 021062 021063 021065 301051 6 001006 002061 301011 301012 301021 008004 301055 7 001005 002001 301011 301012 301021 001012 001014 301062 3 101000 031001 301001 301065 8 001006 001008 002001 002002 002005 002062 002070 002065 301066 6 301011 301013 301023 007004 002064 008004 301070 3 002143 002142 002144 301071 5 001007 001031 002020 002028 002029 301072 4 301071 301011 301013 301021 301074 4 002143 002142 002145 002146 301075 6 301001 001015 301024 008021 301011 301012 301076 3 002011 002143 002142 301090 6 301004 301011 301012 301021 007030 007031 301091 10 002180 002181 002182 002183 002184 002179 002186 002187 002188 002189 301092 9 001011 001003 002001 301011 301012 301021 007030 007031 033024 301093 3 301036 007030 007031 301110 5 301001 001011 002011 002014 002003 301111 6 301001 001011 002011 002013 002014 002003 301112 5 001006 002011 002013 002014 002003 301113 3 008021 301011 301013 301114 5 301021 007030 007031 007007 033024 301120 4 301001 001094 002011 301121 301121 5 008041 301122 301021 007031 007007 301122 7 301011 301012 201135 202130 004006 202000 201000 301123 33 102002 008041 001062 301001 001094 002011 001018 001095 025061 025068 001082 001083 001081 002067 002066 002014 025067 025065 025066 002095 002096 002097 002016 002083 002080 002081 001093 002084 002085 002086 002082 008041 301011 301125 6 001033 001034 025060 001007 002019 001012 301193 5 001007 001031 002196 002221 002222 301194 9 001194 001012 001013 002011 002012 301011 301012 301023 007001 301195 9 001195 001012 001013 002011 002012 301011 301012 301023 007001 301196 7 301003 002011 002012 301011 301012 301023 007001 301197 9 001006 001008 002061 002062 002002 002005 002070 002063 002001 301198 9 001011 001012 001013 002011 002012 301011 301012 301023 007001 301200 2 001032 033194 301201 2 101003 033193 301202 2 001031 001032 301237 12 001007 001012 002021 301011 004004 004005 201138 202131 004006 201000 202000 301023 301238 14 002104 002121 002113 002026 002027 002111 002192 202127 001013 202126 007001 202000 025010 021194 301239 5 002111 002112 021192 021193 021195 301240 5 201131 202129 022021 201000 202000 301241 5 201141 202130 007001 201000 202000 301242 6 021207 021208 021209 021210 021211 021212 301250 4 301193 301011 301013 301021 302001 4 010004 010051 010061 010063 302002 5 010004 007004 010003 010061 010063 302003 9 011011 011012 012004 012006 013003 020001 020003 020004 020005 302004 7 020010 008002 020011 020013 020012 020012 020012 302005 4 008002 020011 020012 020013 302006 4 010004 010051 010062 010063 302011 3 302001 302003 302004 302012 3 302002 302003 302004 302013 5 302006 302003 101000 031001 302005 302021 3 022001 022011 022021 302022 3 022002 022012 022022 302023 3 022003 022013 022023 302024 3 302022 101002 302023 302031 4 302001 010062 007004 010009 302032 4 007032 012101 012103 013003 302033 2 007032 020001 302034 2 007032 013023 302035 8 302032 302033 302034 007032 302004 101000 031001 302005 302036 7 105000 031001 008002 020011 020012 020014 020017 302037 3 020062 013013 012113 302038 4 020003 004024 020004 020005 302039 2 004024 014031 302040 4 007032 102002 004024 013011 302041 7 007032 004024 004024 012111 004024 004024 012112 302042 11 007032 002002 008021 004025 011001 011002 008021 103002 004025 011043 011041 302043 7 302038 101002 302039 302040 302041 302042 007032 302044 3 004024 002004 013033 302045 7 004024 014002 014004 014016 014028 014029 014030 302046 3 004024 004024 012049 302047 3 102003 008002 020054 302048 5 005021 007021 020012 005021 007021 302049 7 008002 020011 020013 020012 020012 020012 008002 302050 31 008041 005021 007005 202130 006021 202000 008041 201131 202129 002115 010004 002115 013003 202000 201000 002115 011001 011002 002115 102002 012101 004024 002115 012103 012102 101003 020012 020011 020013 101002 020003 302051 12 010004 010051 007004 010003 012004 012051 012016 012017 013004 102004 008051 008020 302052 7 007032 007033 012101 002039 012102 012103 013003 302053 3 007032 007033 020001 302054 9 302052 302053 007033 302034 007032 302004 101000 031001 302005 302055 8 020031 020032 020033 020034 020035 020036 020037 020038 302056 4 002038 007063 022043 007063 302057 3 302056 302021 302024 302058 8 007032 007033 004024 004024 012111 004024 004024 012112 302059 12 007032 007033 002002 008021 004025 011001 011002 008021 103002 004025 011043 011041 302060 4 302038 302040 302058 302059 302062 24 302001 302052 302053 007033 101000 031000 302034 007032 101000 031001 302005 008002 101000 031000 302055 101000 031000 302056 101000 031000 302021 101000 031000 302024 302063 8 302038 101000 031000 302040 101000 031000 302058 302059 302066 16 020023 020024 020027 020054 020023 020027 020054 020025 020026 020027 020040 020066 020027 020021 020067 020027 302069 4 007032 007033 033041 020001 302070 8 007032 007033 011001 011002 011043 011041 011016 011017 302071 14 007032 007033 008021 004025 011001 011002 008021 103002 004025 011043 011041 004025 011016 011017 302072 5 007032 007033 012101 012103 013003 302073 7 020010 105004 008002 020011 020012 033041 020013 302074 4 020003 004025 020004 020005 302075 5 008021 004025 013055 013058 008021 302076 7 020021 020022 026020 020023 020024 020025 020026 302077 8 007032 007033 004025 012111 012112 007032 004025 012112 302078 4 002176 020062 002177 013013 302079 5 007032 002175 002178 004025 013011 302080 3 002185 004025 013033 302081 2 004025 014031 302082 7 004025 014002 014004 014016 014028 014029 014030 302083 8 004025 008023 010004 011001 011002 012101 013003 008023 302205 5 201131 202129 022021 201000 202000 302206 9 302205 201130 202129 022011 201000 202000 022001 011001 011002 302207 5 022193 022194 022195 022196 022197 302250 5 102000 031001 020193 020194 020012 303001 3 007003 011001 011002 303002 3 007004 011001 011002 303003 4 007004 010003 012001 012003 303004 6 007004 010003 012001 012003 011001 011002 303011 4 007003 008001 011001 011002 303012 4 007004 008001 011001 011002 303013 7 007004 008001 010003 012001 013003 011001 011002 303014 7 007004 008001 010003 012001 012003 011001 011002 303021 4 007004 007004 204007 031021 303022 3 303021 010003 204000 303023 3 303021 012001 204000 303024 3 303021 013016 204000 303025 5 002025 204007 031021 012063 204000 303026 6 007004 008003 204007 031021 012001 204000 303027 5 007004 204007 031021 010003 204000 303031 6 007004 008003 007021 007022 008012 012061 303032 2 020011 020016 303033 2 020010 020016 303040 18 008041 004025 004026 301021 301122 201131 202129 025069 007004 013003 202000 201000 002013 012101 010009 102002 008040 035035 303041 8 002152 002023 007004 011001 011002 002153 002154 012071 303050 7 004086 008042 007004 005015 006015 011001 011002 303051 7 004086 008042 007004 005015 006015 011061 011062 303052 7 004086 008042 007009 005015 006015 011001 011002 303053 7 004086 008042 007009 005015 006015 011061 011062 303054 10 004086 008042 007004 010009 005015 006015 012101 012103 011001 011002 303249 7 002252 104000 031001 002199 007004 007004 013003 303250 8 002252 002023 007004 011001 011002 002197 002198 012193 303251 8 002252 105000 031001 002254 002251 002197 002198 012063 303252 8 002252 105000 031001 002254 002251 002197 002198 012194 304001 5 008003 010004 012001 011001 011002 304002 4 008003 010004 011001 011002 304003 2 008003 012001 304004 4 008003 010004 020010 012001 304005 4 002024 007004 007004 013003 304006 3 014001 014001 014003 304011 27 002163 002164 008012 007024 002057 008021 004001 004002 004003 004004 008021 004024 110004 008021 004004 004005 004006 008021 004004 004005 004006 011001 011002 103010 002163 007004 012001 304030 3 027031 028031 010031 304031 3 001041 001042 001043 304032 5 002153 002154 020081 020082 020012 304033 8 002152 002166 002167 002153 002154 012075 012076 012063 304034 9 102004 027001 028001 007022 005043 020010 020016 033003 010040 304035 15 002153 002154 012063 008001 012063 008001 012063 008001 008003 012063 008003 012063 008003 012063 008003 304036 12 020082 008012 020082 008012 020081 008003 020081 008003 020081 008003 020081 008003 304228 3 005217 006217 007217 304229 3 001208 001209 001210 304250 27 002231 002232 008012 007024 002057 008021 004001 004002 004003 004004 008021 004024 110004 008021 004004 004005 004006 008021 004004 004005 004006 011001 011002 103010 002231 007004 012001 305003 5 301012 004065 101000 031001 305001 305006 6 013072 013082 013019 012001 013073 013060 305007 6 301029 301012 004065 101000 031001 305006 305008 2 305006 012030 305009 6 301029 301012 004065 101000 031001 305008 305011 6 301029 301012 004065 101000 031001 305010 305018 8 301029 301012 004065 103000 031001 305008 305016 305017 306001 5 002032 102000 031001 007062 022042 306002 3 002031 022004 022031 306003 4 002002 011011 011012 012004 306004 7 002032 002033 103000 031001 007062 022043 022062 306005 6 002031 103000 031001 007062 022004 022031 306006 3 306003 306002 022063 306007 6 001012 001014 306008 004024 027003 028003 306008 3 002034 002035 002036 306019 8 001075 301011 301012 022042 022120 022121 004015 004065 306020 4 306024 102006 022038 022039 306021 7 001075 301011 301012 022122 022123 012001 303002 306022 5 001075 301011 301012 022038 022039 306023 8 001015 301023 301011 301012 022038 022039 022120 022121 306024 8 001075 301011 301012 022042 022120 022121 004025 004015 306025 4 306019 102006 022038 022039 307001 2 301031 302011 307002 2 301032 302011 307003 4 307001 101000 031001 302005 307004 4 307002 101000 031001 302005 307005 3 307001 101004 302005 307006 3 307002 101004 302005 307007 2 301031 302012 307008 2 301032 302012 307009 2 301031 302013 307011 16 001063 002001 301011 301012 301024 007006 011001 011016 011017 011002 011041 007006 012001 012003 010052 020009 307012 5 103000 031001 008023 005021 020001 307013 8 106000 031001 001064 008014 020061 008014 020061 020018 307014 3 101000 031001 020019 307015 4 101000 031001 302005 020002 307016 3 101000 031001 020020 307017 3 101000 031001 011070 307018 16 008016 102000 031001 008017 301012 104000 031001 007006 011001 011002 011041 020009 101000 031001 020001 307014 307020 3 307011 307014 307016 307021 9 307011 307012 307013 307014 307015 307016 307017 307018 307015 307022 31 001015 301011 301012 301022 008021 004025 010004 012001 013003 033038 008022 106025 002020 001050 005021 007021 015031 015032 008060 015033 015034 008060 015033 015034 015035 201131 202129 013016 202000 201000 015011 307030 2 015001 015002 307031 7 008022 008023 015001 008023 015001 008023 015002 307041 7 301001 001015 301022 301011 301012 301070 307030 307042 9 301001 001015 301022 301011 301012 008021 004025 301070 307031 307043 7 301001 001015 301024 301011 301012 301074 307030 307045 25 001063 008079 002001 301011 301012 301024 007032 011001 011016 011017 008054 011083 011084 011002 008054 011085 011086 011041 008054 007032 012023 012024 007032 010052 020009 307046 5 020060 Metar/speci visibility 102000 031001 005021 020059 307047 9 105000 Metar/speci clouds 031001 008002 020011 020012 020013 020092 020002 020091 307048 25 008016 102000 031001 008017 301012 112000 031000 007032 011001 008054 011083 011084 011002 008054 011085 011086 011041 008054 007032 020009 101000 031000 020060 307014 307047 307049 4 102000 031000 022043 022021 307050 14 101000 031000 020085 102000 031001 001064 020085 105000 031001 001064 020086 020087 020088 020089 307059 12 307045 Full METAR/SPECI 307046 307013 307014 307047 307016 307017 307049 307050 101000 031001 307048 Trend forecast 307052 12 001063 008039 301011 301012 008079 008039 301011 start of forecast 301012 008039 301011 end of forecast 301012 301024 307053 16 007032 011001 008054 011083 011084 011002 008054 011085 011086 011041 008054 007032 020009 020060 307014 307047 307054 13 007032 008039 004003 004004 008023 012023 008039 004003 004004 008023 012023 008023 007032 307055 9 033045 008016 008039 004003 301012 008039 004003 301012 307053 307056 6 307052 Aerodrome forecast 307053 307054 101000 031001 307055 307059 12 307045 Full METAR/SPECI 307046 307013 307014 307047 307016 307017 307049 307050 101000 031001 307048 Trend forecast 307060 2 007061 012030 307061 3 301031 101005 307060 307062 3 301032 101005 307060 307063 2 007061 012130 307071 67 301090 004074 004023 008023 010004 010051 007004 010009 007032 012101 002051 004051 012118 004052 012119 013004 008023 012151 007032 102005 008050 008020 014032 014033 008050 008020 102018 008052 008022 007032 008053 004003 012152 008053 004003 012153 008053 004003 008023 012101 008053 004003 008023 012101 008023 007032 002002 008053 004003 011046 008053 004003 004004 004023 007032 013060 013051 004053 008050 008020 102006 008052 008022 008053 004003 013052 007032 307072 38 004001 004001 004002 004003 004004 004074 004022 008023 010004 010051 007004 010009 007032 012101 002051 004051 012118 004052 012119 013004 012151 007032 014032 008023 004001 004001 004002 004003 004004 004022 007032 008023 013060 004053 008023 102008 008050 008020 307073 2 307071 307072 307079 30 301090 SYNOP data and marine data from costal stations 302031 302035 302036 101000 031000 302047 008002 101000 031000 302048 302037 102000 031000 022061 020058 101000 031000 302056 101000 031000 302055 302043 302044 101000 031001 302045 101000 031000 302046 307080 13 301090 BUFR template for synoptic reports 302031 302035 302036 302047 008002 302048 302037 302043 302044 101002 302045 302046 307081 24 301090 BUFR template for synoptic reports RA I 302031 302035 302036 302047 008002 302048 302037 012122 013056 013057 020101 020102 020103 020104 020105 020106 020107 020108 302043 302044 101002 302045 302046 307082 15 301090 BUFR template for synoptic reports RA II 302031 302035 302036 302047 008002 302048 302037 012121 012122 302043 302044 101002 302045 302046 307083 14 301090 BUFR template for synoptic reports RA III 302031 302035 302036 302047 008002 302048 302037 012122 302043 302044 101002 302045 302046 307084 17 301090 BUFR template for synoptic reports RA IV 302031 302035 302036 302047 008002 302048 302037 020055 101000 031000 205001 302043 302044 101002 302045 302046 307086 11 301090 BUFR template for synoptic reports RA VI 302031 302035 302036 008002 302037 302066 302043 302044 101002 302045 307090 13 301092 BUFR template for synoptic reports from mobile land stations 302031 302035 302036 302047 008002 302048 302037 302043 302044 101002 302045 302046 307091 66 301089 301090 008010 301091 302001 007004 010009 302072 103000 031000 101005 307063 007061 101000 031000 302069 007032 007033 105000 031000 020031 020032 002038 022043 302021 101000 031000 302078 101000 031000 302073 101000 031000 302074 101000 031000 302075 102000 031000 004025 302076 302071 302077 007033 101000 031000 302079 007032 101000 031000 302080 101000 031000 302081 101000 031000 302082 102000 031000 004025 013059 101000 031000 302083 033005 033006 307092 62 301089 Surface obs drom N-minute period 301090 008010 301091 004015 004065 125000 031001 010004 302070 302072 007032 012101 103000 031000 101005 307063 007061 101000 031000 302069 007032 007033 101000 031000 302073 101000 031000 302076 102000 031000 013055 013058 102000 031000 020031 020032 101000 031000 302078 102000 031000 302079 007032 101000 031000 302080 101000 031000 302081 101000 031000 302083 102000 031000 004025 013059 101000 031000 302083 033005 033006 308001 3 301033 302011 022042 308002 3 301034 302011 022042 308003 3 301035 302011 022042 308004 3 301036 302011 022042 308005 2 308004 302024 308006 8 010004 010061 010063 011001 011002 012004 013003 022042 308007 4 301055 302011 007062 022042 308008 84 001003 BUOY 001020 001005 002001 002036 002149 301011 301012 008021 301011 301012 008021 301021 027004 028004 007030 001051 002148 001012 001014 002040 033022 033023 033027 022063 302021 302022 302023 008081 025026 008081 025026 008081 025026 008081 002034 022060 007070 002190 025086 002035 002168 020031 002038 306004 002030 306005 007031 008081 012064 302001 008081 007032 007033 012101 012103 013003 007032 007033 008082 007033 002169 002002 008021 004025 011001 011002 008021 004025 011043 011041 008082 007033 007032 004024 013011 007032 008021 004024 014021 008021 025028 025028 025028 308009 7 301093 302001 302054 008002 302055 302057 302060 308010 16 001011 TRACKOB template 113000 031001 301011 301012 301021 004080 022049 004080 022059 004080 022005 002042 022032 002042 004080 308011 27 001011 Climat ship 002001 301011 301012 301023 007030 007031 004074 004023 008023 010051 007032 007033 012101 013004 007032 007033 302056 008023 004003 004004 004023 007032 013060 013051 004053 007032 308012 28 004001 Monthly normals from an ocean weather station 004001 004002 004003 004004 004074 004022 008023 010051 007032 007033 012101 013002 007032 007033 302056 008023 004001 004001 004002 004003 004004 004022 007032 008023 013060 004053 008023 308013 2 308011 308012 309001 4 301037 101000 031001 303011 309002 4 301038 101000 031001 303011 309003 4 301037 101000 031001 303012 309004 4 301038 101000 031001 303012 309005 5 301037 302004 101000 031001 303013 309006 5 301038 302004 101000 031001 303013 309007 5 301037 302004 101000 031001 303014 309008 5 301038 302004 101000 031001 303014 309011 4 301039 101000 031001 303011 309012 4 301039 101000 031001 303012 309013 5 301039 302004 101000 031001 303013 309014 5 301039 302004 101000 031001 303014 309015 4 301040 101000 031001 303011 309016 4 301040 101000 031001 303012 309017 5 301040 302004 101000 031001 303013 309018 5 301040 302004 101000 031001 303014 309019 5 301031 002003 101000 031001 303011 309020 8 301031 002003 104000 031001 007003 011003 011004 011005 309030 8 015004 015005 104000 031001 004015 008006 007004 015003 309031 8 015004 015005 104000 031001 004025 008006 007004 015003 309040 3 301075 301076 309030 309042 4 307042 301075 301076 309030 309050 9 301110 301113 301114 101000 031002 303050 101000 031001 303051 309051 9 301110 301113 301114 101000 031002 303052 101000 031001 303053 309052 11 301111 301113 301114 302049 022043 101000 031002 303054 101000 031001 303051 309053 9 301112 301113 301114 101000 031002 303054 101000 031001 303051 309054 27 301001 001011 301011 301012 301021 007030 007031 007007 004023 004059 115000 031001 008001 008023 007004 010009 012101 012103 008023 011001 011002 008023 011019 008050 008020 008050 008020 309060 4 301123 301121 302050 303040 309061 21 301120 008041 301122 201131 202129 025069 007004 202000 201000 033007 033035 033015 013009 033007 033035 033015 002013 012101 033007 033035 033015 309062 19 301120 008041 301122 005001 033035 033015 006001 033035 033015 007007 033035 033015 011003 033035 033015 011004 033035 033015 033007 309063 19 301120 008041 301122 005001 033035 033015 006001 033035 033015 007007 033035 033015 011003 033035 033015 011004 033035 033015 033007 309064 26 301120 008041 301122 201131 202129 104002 025069 007004 033035 033015 013003 033035 033015 202000 201000 104002 002013 012101 033035 033015 012103 033035 033015 010009 033035 033015 309065 18 301120 008041 301122 005001 033035 033015 006001 033035 033015 007007 033035 033015 011003 033035 033015 011004 033035 033015 309066 18 301120 008041 301122 008040 201131 202129 025069 007004 013003 202000 201000 002013 012101 012103 010009 010007 011002 011001 309194 5 301194 302004 101000 031001 303014 309195 5 301195 302004 101000 031001 303014 309196 5 301196 302004 101000 031001 303014 309198 5 301198 302004 101000 031001 303014 310001 5 301042 303031 303032 101026 303025 310002 5 301042 303031 303032 101009 303023 310003 5 301042 303031 303032 101006 303023 310004 5 301042 303031 303032 101003 303024 310005 6 301042 303031 303033 101000 031001 303025 310006 6 301042 303031 303033 101000 031001 303023 310007 6 301042 303031 303033 101000 031001 303024 310008 8 310011 101019 310012 002150 025079 025080 033032 014045 310009 3 310011 101015 310012 310010 3 310011 101005 310012 310011 45 008070 001033 001034 008070 001033 001034 001007 002048 005040 025075 201133 005041 201000 005043 025070 033030 033031 004001 004002 004003 004004 004005 202131 201138 004006 201000 202000 005001 006001 202126 007001 202000 007024 005021 007025 005022 033033 002151 012064 002151 012064 002151 012064 002151 012064 310012 10 002150 025076 025077 025078 033032 201132 202129 012063 202000 201000 310013 62 001007 005040 004001 004002 004003 004004 004005 004006 005001 006001 007025 005043 025085 201131 202129 002150 008023 008072 014027 008072 014027 002150 008023 008072 014027 008072 014027 002150 008023 008072 014027 008072 014027 202000 201000 201132 202129 002150 008023 008072 012063 008072 012063 002150 008023 008072 012063 008072 012063 008023 008072 012063 008072 012063 002150 008023 008072 012063 008072 012063 202000 201000 310014 3 301072 303041 304011 310015 13 301072 007024 010002 303041 101003 304032 002152 002024 007004 007004 013003 101003 304033 310016 13 301072 007024 010002 303041 101012 304032 002152 002024 007004 007004 013003 101012 304033 310019 68 001007 002019 301011 301013 301023 007025 008021 007025 008021 007025 008021 008029 005040 008075 008003 010004 008003 207002 015001 207000 033070 015030 207002 020081 207000 008003 033042 007004 207002 015001 207000 008003 113021 007004 007004 207002 008021 015005 008021 015005 033007 207000 008026 101020 025143 008026 008043 109015 007004 008090 207006 015008 207000 008090 207002 033007 207000 008043 033071 108008 202124 201107 002071 201000 202000 207002 020081 207000 310020 6 310022 301011 301013 301021 304034 310021 310021 10 108000 031001 201131 202129 007004 007004 202000 201000 015020 010002 310022 4 001007 002019 001033 002172 310023 17 301072 030021 030022 008012 007024 007025 010002 101012 304032 105002 002152 002024 007004 007004 013003 101012 304033 310024 17 301072 030021 030022 008012 007024 007025 010002 101003 304032 105002 002152 002024 007004 007004 013003 101003 304033 310025 61 001007 008021 004001 004002 004003 004004 004005 201138 202131 004006 202000 201000 201132 005041 201000 201129 005043 201000 005002 006002 013040 020029 104024 005042 012163 021083 021084 115003 004001 004002 004003 201142 202131 004026 202000 201000 005001 006001 201138 202129 007001 202000 201000 008021 004001 004002 004003 004004 004005 005040 101003 012070 025054 101004 025055 008007 104028 005002 006002 002111 005021 310026 82 310022 025060 008021 301011 301012 201138 202131 004006 202000 201000 033039 033007 304030 304031 002020 001050 202127 304030 202000 304031 201133 202131 004016 202000 201000 301021 304030 010035 005021 010036 113000 031002 301021 005021 108000 031001 002121 007040 015037 008023 201125 015037 201000 008023 033007 108000 031002 007007 015036 008023 201123 015036 201000 008023 033007 116000 031002 007009 010004 012001 013001 008023 201120 010004 201000 201122 012001 201000 201123 013001 201000 008023 033007 008003 007009 010004 008023 201120 010004 201000 008023 033007 310027 12 301071 301011 301013 301021 030021 030022 010002 304036 002152 002167 101011 304035 310029 12 110000 031001 201138 202130 007004 007004 202000 201000 015020 010002 012101 013098 310030 6 310022 301011 301013 301021 304034 310029 310050 14 310051 310052 101000 031002 310053 101004 310054 020010 310052 101015 310053 310052 101005 310053 310051 16 001007 005040 201133 005041 201000 201132 025070 201000 202126 007001 202000 007025 005022 102009 002151 012064 310052 12 002019 301011 301012 202131 201138 004006 201000 202000 301021 007024 005021 005043 310053 6 201134 005042 201000 025076 033032 012163 310054 13 201134 005042 201000 025076 033032 201131 202129 102002 008023 014027 008023 202000 201000 310055 8 310051 310052 102020 025076 025052 101000 031002 025050 310060 53 001007 001033 002019 002020 301011 301012 207003 004006 207000 304030 301021 007024 005021 007025 005022 008075 201133 005041 201000 005045 005043 005040 010001 201129 007002 201000 202127 201125 021166 201000 202000 008012 020010 020014 002165 033075 107003 008076 006029 006029 025140 025141 033076 033077 008076 033078 033003 104000 031002 201133 005042 201000 014044 310193 5 301250 303250 302250 303249 303251 310194 5 301250 303250 302250 303249 303252 310195 3 301250 303250 304250 310196 3 301250 303249 303251 310226 39 310022 025060 008021 301011 301012 201138 202131 004006 202000 201000 033039 033007 304030 304031 002020 001050 202127 304030 202000 304031 201133 202131 004016 202000 201000 301021 304030 010035 005021 010036 107000 031002 301021 005021 103000 031001 002121 007040 015037 311001 9 301051 007002 012001 011001 011002 011031 011032 011033 020041 311002 4 301065 301066 311003 311004 311003 5 010070 011001 011002 012001 013002 311004 18 101000 031000 011034 101000 031000 011035 101000 031000 011075 101000 031000 011076 101000 031000 033025 101000 031000 033026 311005 13 001008 001023 301021 301011 301013 007010 008009 011001 011002 011031 011036 012101 033025 311006 6 007010 011001 011002 002064 012101 012103 311007 7 007010 301021 011001 011002 002064 012101 012103 311008 8 001008 301011 301013 301021 008004 101000 031001 311006 311009 8 001008 301011 301013 301021 008004 101000 031001 311007 311193 16 301197 301011 301012 301023 008004 007004 008021 011001 011002 011031 011034 011035 012001 012003 013003 020041 312001 2 301043 304001 312002 2 301043 304002 312003 2 301042 304003 312004 2 301042 304004 312005 2 301042 020014 312006 2 301044 304005 312007 2 301042 304006 312010 6 001007 005040 002021 005041 004001 004043 312011 9 202131 201149 004006 201000 202126 010002 202000 005043 005053 312012 6 202129 201132 101019 012063 201000 202000 312013 6 005042 202129 201135 012063 201000 202000 312014 8 312010 312011 105056 301023 005042 005052 312012 312013 312015 10 109011 301023 005042 005052 202129 201132 101004 012063 202000 201000 312016 3 312010 312011 312015 312017 10 109008 301023 005042 005052 202129 201132 101003 012063 202000 201000 312018 3 312010 312011 312017 312019 13 301047 301048 015015 029002 021076 106012 201129 006030 201000 102012 005030 021075 021066 312020 11 301047 301048 015015 029002 021076 104012 006030 102012 005030 021075 021066 312021 6 301047 101003 301049 011012 011011 021067 312022 15 301047 008022 011012 011050 022070 022026 312041 010050 021068 021071 021072 021073 312042 021062 015011 312023 7 301047 103003 008022 012061 022050 021069 021085 312024 11 312020 008060 008022 008060 008022 025014 022101 022097 022098 022099 022100 312025 11 312019 008060 008022 008060 008022 025014 022101 022097 022098 022099 022100 312026 19 301046 301011 301013 301023 312031 101004 312030 021110 301023 321027 021111 301023 321027 021112 301023 321027 021113 301023 321027 312027 9 301047 105009 301023 007021 012061 007021 012061 021085 021070 312028 26 301046 301011 301013 301023 008025 201136 004006 201000 312031 312032 101004 312030 101002 312033 021110 301023 321028 021111 301023 321028 021112 301023 321028 021113 301023 321028 312030 13 201130 202129 011012 202000 201000 011052 201135 202130 011011 202000 201000 011053 021104 312031 8 005034 006034 021109 011081 011082 021101 021102 021103 312032 4 021120 021121 013055 021122 312033 4 002104 008022 012063 012065 312041 5 201141 202130 007001 201000 202000 312042 6 021077 021078 021079 021080 021081 021082 312045 21 001007 002019 001096 025061 005040 301011 301013 301021 007002 012180 012181 012182 012183 012184 012185 002174 021086 012186 021087 012187 033043 312050 23 001007 002019 001096 025061 005040 301011 301013 301021 007025 005022 010080 027080 008003 007004 013093 008003 201131 202129 007004 007004 202000 201000 013095 312051 48 001007 002019 001096 025061 005040 008075 301011 301013 301021 001012 201131 001013 201000 010032 010033 010034 007002 008012 025110 025111 025102 002104 025103 025104 025105 025106 025107 025108 002111 002121 002026 002027 021130 021131 021132 021133 021064 025014 021134 107018 005030 105024 201130 006030 201000 021135 021136 033044 312052 77 001007 002019 001096 025061 005040 025120 025121 025124 025125 025122 025123 301011 301013 301021 007002 002119 033047 010081 010082 010083 010084 002116 002117 002118 002156 002157 014055 022150 022151 022152 022153 022154 022155 022156 022157 022158 022159 021137 021138 021139 021140 021141 021142 010085 010086 010087 010088 010089 010090 010091 010092 010093 011002 025126 025127 025128 025129 025130 025131 025132 025133 025134 025135 025136 025137 013096 013097 011095 011096 012188 012189 002158 002159 033052 033053 021143 021144 312053 54 001007 002019 001096 025061 005040 008075 301011 301013 301021 001012 201131 001013 201000 010032 010033 010034 007002 008012 025110 025111 025102 002104 025103 025104 025105 025106 025107 025108 011001 011002 022160 025138 201130 202129 022021 202000 201000 033048 033049 002026 002027 021130 021131 021132 021133 025014 106036 005030 104024 201130 006030 201000 022161 033044 312055 5 005033 005040 006034 010095 021157 312056 11 025060 001032 011082 011081 020095 020096 021155 201133 021101 021102 201000 312057 12 201130 202129 011012 202000 201000 201131 202129 011011 202000 201000 021156 021104 312058 8 301125 301011 301013 301021 312055 021150 101003 321030 312059 4 312056 101000 031001 312057 312060 20 025060 025062 040001 040002 021062 021151 021152 021153 021154 021062 021062 040003 040004 040005 040006 040007 020065 040008 040009 040010 312061 3 312058 312060 312059 312070 27 001007 002019 001144 001124 030010 301011 301013 301021 007012 015012 012165 012166 012167 012168 027010 028010 002099 013048 025081 025082 025083 025084 012080 012081 012082 025174 033028 312200 10 301237 301238 029002 021206 104012 006232 102012 005232 021205 021196 312201 6 301237 101003 301239 011012 011011 021197 312202 13 301237 008022 011012 011050 301240 022243 301241 010050 021198 021201 021202 021203 301242 312203 8 301237 008022 012061 022050 021204 021199 021214 021215 312204 12 312201 001031 011012 011011 021200 021213 004004 008021 004024 055003 011012 011011 312207 3 312202 301202 033191 312208 17 301202 008022 008021 301011 301013 301023 302205 011002 001007 002021 301011 301013 301023 001032 001192 302205 011002 312209 11 301202 001192 301011 301013 301023 302206 104000 022192 102000 005232 022191 312210 13 312202 021192 015202 301011 004004 004005 201138 202131 004006 201000 202000 304228 304229 312211 19 301046 301011 301013 301023 312031 101004 312030 021110 101004 312212 021111 101004 312212 021112 101004 312212 021113 101004 312212 312212 2 301023 321027 313009 4 021001 101000 031001 021001 313010 4 021036 101000 031001 021036 313031 5 006002 006012 101000 031002 030001 313032 5 005002 005012 101000 031002 313031 313041 13 006002 110000 031001 104000 031001 006012 101000 031012 030001 006012 101000 031001 030001 313042 5 005002 005012 101000 031002 313041 313043 17 006002 005002 005012 112000 031001 110000 031001 104000 031001 006012 101000 031011 030001 006012 101000 031001 030001 315001 5 001011 301011 301012 301023 306001 315002 5 001011 301011 301012 301023 306004 315003 25 001087 001085 001086 002036 002148 002149 022055 022056 022067 301011 301012 301021 008080 033050 109000 031002 007065 008080 033050 022045 008080 033050 022064 008080 033050 316001 10 301011 004004 301023 001021 002041 019001 010051 019002 019003 019004 316002 15 008021 004001 004002 004003 004004 004005 001033 008021 004001 004002 004003 004004 004005 007002 007002 316003 12 110000 031001 008011 008007 104000 031001 005002 006002 010002 011002 008007 008011 316004 13 111000 031001 008011 008007 007002 007002 102000 031001 005002 006002 011031 008007 008011 316005 10 108000 031001 008005 008007 005002 006002 001026 019001 008007 008005 316006 14 112000 031001 008011 008007 007002 007002 102000 031001 005002 006002 020011 020012 008007 008011 316007 12 110000 031001 008011 008007 104000 031001 005002 006002 019005 019006 008007 008011 316008 13 111000 031001 008001 008007 008023 103000 031001 005002 006002 010002 008023 008007 008001 316009 13 111000 031001 008011 008007 007002 007002 102000 031001 005002 006002 020041 008007 008011 316010 9 107000 031001 008011 008007 001022 005002 006002 008007 008011 316011 19 117000 031001 008011 001022 008007 102000 031001 005002 006002 008021 004001 004002 004003 004004 004005 020090 008021 008007 008011 316020 5 001023 001025 001027 301011 301012 316021 23 301023 002041 019001 019007 019005 019006 019008 008005 010004 008005 010004 019007 008005 008021 004075 011040 019007 105004 005021 005021 102002 019003 019004 316022 24 001032 002041 019001 019010 118000 031001 008021 004014 008005 301023 019005 019006 010004 011041 008021 004075 011040 019008 105004 005021 005021 102002 019003 019004 316026 2 316020 316021 316030 10 301014 001037 010064 008019 001062 008019 001065 008019 001062 008019 316031 8 008021 301011 301012 301027 019005 019006 020028 008021 316032 5 008021 301011 301012 301027 008021 316033 7 008021 301011 301012 101000 031001 301027 008021 316034 17 008079 316030 008011 001022 008007 301023 008007 020090 316031 101000 031000 316032 101000 031001 316033 008011 008079 316035 9 008079 316030 008011 020023 020021 020008 316031 008011 008079 316036 13 008079 316030 008011 001027 316031 101000 031000 316032 101000 031001 316033 008011 008079 316037 7 008079 316030 008011 011031 316031 008011 008079 316038 8 008079 316030 008011 020041 020021 316031 008011 008079 316039 7 008079 316030 008011 020024 316031 008011 008079 316040 6 316030 008079 301014 001037 010064 008079 316050 16 301001 301011 301012 002160 008005 005002 006002 008005 019100 019005 019006 019101 019102 019103 019104 019105 316052 29 301005 301011 301012 001007 025150 122000 031001 001027 019150 019106 008005 005002 006002 008005 019107 019005 019006 019108 019109 019110 019111 019112 019113 019114 019115 019116 019117 019118 019119 318001 2 301025 024011 318003 4 301026 024005 024004 024021 318004 6 301025 004023 013011 024005 024004 024022 321001 6 002101 002114 002105 002106 002107 002121 321003 4 021051 021014 021017 021030 321004 5 301031 002003 101000 031001 321003 321005 12 025004 002121 002122 002123 002124 002125 002126 002127 002128 002129 002130 002131 321006 4 025001 025002 025003 025005 321007 8 025009 025010 025011 025012 025013 025015 025016 025017 321008 3 025006 025007 025008 321009 2 025018 025019 321010 13 002101 007002 002102 002103 002104 002105 002106 002107 002108 002109 002110 002132 002133 321011 3 030031 030032 029002 321012 3 101000 031001 002135 321021 15 002003 002101 201130 002106 201000 201132 202130 002121 202000 201000 201133 202129 025001 202000 201000 321022 11 007007 204001 031021 011001 204000 011002 204001 031021 011006 204000 021030 321023 9 007007 021091 021030 202129 021014 201129 021017 202000 201000 321024 7 007007 204001 031021 012007 011006 204000 021030 321025 17 007007 021091 021030 202129 021014 201129 021017 202000 201000 021092 021030 025092 201129 202129 021017 202000 201000 321026 10 007007 204001 031021 012007 025091 011071 011072 011073 011074 204000 321027 18 021118 202129 201132 002112 201000 201131 002111 201000 202000 002104 021105 021106 021107 021114 021115 021116 008018 021117 321028 18 021118 202129 201132 002112 201000 201131 002111 201000 202000 002104 021123 021106 021107 021114 021115 021116 008018 021117 321030 18 008085 202129 201131 002111 201000 202000 002134 021062 021063 021158 021159 021160 021161 021162 021163 021164 021165 021166 340001 45 001007 001031 002019 002020 004001 004002 004003 004004 004005 202131 201138 004006 201000 202000 005001 006001 007024 005021 007025 005022 005043 005040 201133 005041 201000 201132 025070 201000 202126 007001 202000 033060 033061 033062 033063 033064 033065 101010 340002 101087 340003 002019 025051 101007 340004 340002 3 025140 025141 025142 340003 5 104100 201136 005042 201000 014046 340004 9 005060 005061 025085 105006 005042 025142 014047 025142 014048 340005 94 001007 002019 001096 025061 005044 005040 001030 301011 301012 004007 005001 006001 008029 008074 008077 040011 025097 025095 025098 025099 021144 025096 040012 040013 021169 022151 022162 022163 025160 025133 022156 022164 022165 022166 021137 021138 022167 021139 021118 021145 021146 021147 022168 022169 022170 025161 025162 022171 022172 022173 022174 021170 021171 022175 021172 021118 021173 021174 021175 102003 002153 012063 013090 013091 007002 011097 011098 007002 011095 011096 010096 010081 010082 010083 010101 025132 025163 025126 025128 025164 010085 010097 010086 010087 010092 010088 010089 010098 010099 010090 010100 010093 025127 040014 340007 57 001007 001031 002019 002020 004001 004002 004003 004004 004005 202131 201138 004006 201000 202000 005001 006001 007024 005021 007025 005022 005043 005040 201133 005041 201000 201132 025070 201000 202126 007001 202000 103003 025140 025141 033060 033061 033062 033063 033064 033065 040020 101010 340002 101087 340003 002019 025051 101007 340004 020081 008029 020083 008029 040018 040019 040021 040022 340008 70 001007 001031 002019 002020 004001 004002 004003 004004 004005 202131 201138 004006 201000 202000 005001 006001 007024 005021 007025 005022 005043 005040 201133 005041 201000 201132 025070 201000 202126 007001 202000 103003 025140 025141 033060 033061 033062 033063 033064 033065 040020 101010 340002 104000 031002 201136 005042 201000 014046 108003 025140 025141 040015 040016 025062 101000 031002 040017 002019 025051 101007 340004 020081 008029 020083 008029 040018 040019 040021 040022 dballe-7.7/tables/D990204.txt0000644000175000017500000052523112652630043012432 00000000000000 D00002 2 B00002 B00003 D00003 3 B00010 B00011 B00012 D00004 9 D00003 B00013 B00014 B00015 B00016 B00017 B00018 B00019 B00020 D00010 3 D00003 R01000 B00030 D01001 2 B01001 B01002 D01002 3 B01003 B01004 B01005 D01003 3 B01011 B01012 B01013 D01004 4 B01001 B01002 B01015 B02001 D01011 3 B04001 B04002 B04003 D01012 2 B04004 B04005 D01013 3 B04004 B04005 B04006 D01021 2 B05001 B06001 D01022 3 B05001 B06001 B07001 D01023 2 B05002 B06002 D01024 3 B05002 B06002 B07001 D01025 3 D01023 B04003 D01012 D01026 7 D01021 B04003 B04003 B04004 B04004 B04005 B04005 D01029 3 B01018 B02001 D01011 D01030 4 B01018 B02001 D01011 D01024 D01031 5 D01001 B02001 D01011 D01012 D01022 D01032 5 D01001 B02001 D01011 D01012 D01024 D01033 5 B01005 B02001 D01011 D01012 D01021 D01034 5 B01005 B02001 D01011 D01012 D01023 D01035 7 B01005 B01012 B01013 B02001 D01011 D01012 D01023 D01036 5 D01003 B02001 D01011 D01012 D01023 D01037 6 D01001 B02011 B02012 D01011 D01012 D01022 D01038 6 D01001 B02011 B02012 D01011 D01012 D01024 D01039 6 D01003 B02011 B02012 D01011 D01012 D01023 D01040 6 D01003 B02011 B02012 D01011 D01012 D01024 D01041 5 B01007 B02021 B02022 D01011 D01012 D01042 2 D01041 D01021 D01043 5 B01007 B02023 D01011 D01013 D01021 D01044 5 B01007 B02024 D01011 D01013 D01021 D01049 5 B02111 B02112 B21062 B21063 B21065 D01051 6 B01006 B02061 D01011 D01012 D01021 B08004 D01055 7 B01005 B02001 D01011 D01012 D01021 B01012 B01014 D01062 2 R01000 D01001 D01065 8 B01006 B01008 B02001 B02002 B02005 B02062 B02070 B02065 D01066 6 D01011 D01013 D01023 B07004 B02064 B08004 D01070 3 B02143 B02142 B02144 D01071 5 B01007 B01031 B02020 B02028 B02029 D01072 4 D01071 D01011 D01013 D01021 D01074 4 B02143 B02142 B02145 B02146 D01075 6 D01001 B01015 D01024 B08021 D01011 D01012 D01076 3 B02011 B02143 B02142 D01090 6 D01004 D01011 D01012 D01021 B07030 B07031 D01091 10 B02180 B02181 B02182 B02183 B02184 B02179 B02186 B02187 B02188 B02189 D01193 5 001007 001031 002196 002221 002222 D01250 4 D01193 D01011 D01013 D01021 D02001 4 B10004 B10051 B10061 B10063 D02002 5 B10004 B07004 B10003 B10061 B10063 D02003 9 B11011 B11012 B12004 B12006 B13003 B20001 B20003 B20004 B20005 D02004 7 B20010 B08002 B20011 B20013 B20012 B20012 B20012 D02005 4 B08002 B20011 B20012 B20013 D02006 4 B10004 B10051 B10062 B10063 D02011 3 D02001 D02003 D02004 D02012 3 D02002 D02003 D02004 D02013 4 D02006 D02003 R01000 D02005 D02021 3 B22001 B22011 B22021 D02022 3 B22002 B22012 B22022 D02023 3 B22003 B22013 B22023 D02024 3 D02022 R01002 D02023 D02051 12 B10004 B10051 B07004 B10003 B12004 B12051 B12016 B12017 B13004 R02004 B08051 B08020 D02069 4 B07032 B07033 B33041 B20001 D02070 8 B07032 B07033 B11001 B11002 B11043 B11041 B11016 B11017 D02071 14 B07032 B07033 B08021 B04025 B11001 B11002 B08021 R03002 B04025 B11043 B11041 B04025 B11016 B11017 D02072 5 B07032 B07033 B12101 B12103 B13003 D02073 7 B20010 R05004 B08002 B20011 B20012 B33041 B20013 D02074 4 B20003 B04025 B20004 B20005 D02075 5 B08021 B04025 B13055 B13058 B08021 D02076 7 B02021 B20022 B26020 B20023 B20024 B20025 B20026 D02077 12 B07032 B07033 B04025 B12111 B12112 B07032 B04025 B12112 B02176 B20062 B02177 B13013 D02078 4 B02176 B20062 B02177 B13013 D02079 5 B07032 B02175 B02178 B04025 B13011 D02080 3 B02185 B04025 B13033 D02081 2 B04025 B14031 D02082 7 B04025 B14002 B14004 B14016 B14028 B14029 B14030 D02083 8 B04025 B08023 B10004 B11001 B11002 B12101 B13003 B08023 D03001 3 B07003 B11001 B11002 D03002 3 B07004 B11001 B11002 D03003 4 B07004 B10003 B12001 B12003 D03004 6 B07004 B10003 B12001 B12003 B11001 B11002 D03011 4 B07003 B08001 B11001 B11002 D03012 4 B07004 B08001 B11001 B11002 D03013 7 B07004 B08001 B10003 B12001 B13003 B11001 B11002 D03014 7 B07004 B08001 B10003 B12001 B12003 B11001 B11002 D03031 6 B07004 B08003 B07021 B07022 B08012 B12061 D03032 2 B20011 B20016 D03033 2 B20010 B20016 D03041 8 B02152 B02023 B07004 B11001 B11002 B02153 B02154 B12071 D03250 8 B02252 B02023 B07004 B11001 B11002 B02197 B02198 B12193 D04001 5 B08003 B10004 B12001 B11001 B11002 D04002 4 B08003 B10004 B11001 B11002 D04003 2 B08003 B12001 D04004 4 B08003 B10004 B20010 B12001 D04005 4 B02024 B07004 B07004 B13003 D04006 3 B14001 B14001 B14003 D04011 27 B02163 B02164 B08012 B07024 B02057 B08021 B04001 B04002 B04003 B04004 B08021 B04024 R10004 B08021 B04004 B04005 B04006 B08021 B04004 B04005 B04006 B11001 B11002 R03010 B02163 B07004 B12001 D04030 3 B27031 B28031 B10031 D04031 3 B01041 B01042 B01043 D04032 5 B02153 B02154 B20081 B20082 B20012 D04033 8 B02152 B02166 B02167 B02153 B02154 B12075 B12076 B12063 D04034 9 R02004 B27001 B28001 B07022 B05043 B20010 B20016 B33003 B10040 D04250 27 B02231 B02232 B08012 B07024 B02057 B08021 B04001 B04002 B04003 B04004 B08021 B04024 R10004 B08021 B04004 B04005 B04006 B08021 B04004 B04005 B04006 B11001 B11002 R03010 B02231 B07004 B12001 D05001 4 B11001 B11002 B13060 B13071 D05002 11 D01012 B12001 B13003 B14051 B13060 B13072 B13080 B13081 B13082 B13083 B13084 D05003 4 D01012 B04065 R01000 D05001 D05004 3 D01030 D05002 D05003 D05006 8 B13072 B13082 B13019 C07005 C01004 B12001 B13073 B13060 D05007 5 D01029 D01012 B04065 R01000 D05006 D05008 4 D05006 C07005 C01004 B12030 D05009 5 D01029 D01012 B04065 R01000 D05008 D05010 3 D05008 B02091 B02091 D05011 5 D01029 D01012 B04065 R01000 D05010 D05016 7 B14021 B07004 B13003 B11002 B11001 B11041 B11043 D05017 5 B13080 B13081 B13083 B13085 B13084 D05018 7 D01029 D01012 B04065 R03000 D05008 D05016 D05017 D06001 4 B02032 R02000 B07062 B22042 D06002 3 B02031 B22004 B22031 D06003 4 B02002 B11011 B11012 B12004 D06004 6 B02032 B02033 R03000 B07062 B22043 B22062 D06005 5 B02031 R03000 B07062 B22004 B22031 D06006 3 D06003 D06002 B22063 D06007 6 B01012 B01014 D06008 B04024 B27003 B28003 D06008 3 B02034 B02035 B02036 D06020 8 B01075 D01011 D01012 B22042 B22120 B22121 B04075 B04065 D06021 7 B01075 D01011 D01012 B22122 B22123 B12001 D03002 D06022 5 B01075 D01011 D01012 B22038 B22039 D06023 8 B01015 D01023 D01011 D01012 B22038 B22039 B22120 B22121 D06024 4 D06020 R02000 B22038 B22039 D07001 2 D01031 D02011 D07002 2 D01032 D02011 D07003 3 D07001 R01000 D02005 D07004 3 D07002 R01000 D02005 D07005 3 D07001 R01004 D02005 D07006 3 D07002 R01004 D02005 D07007 2 D01031 D02012 D07008 2 D01032 D02012 D07009 2 D01031 D02013 D07011 16 B01063 B02001 D01011 D01012 D01024 B07006 B11001 B11016 B11017 B11002 B11041 B07006 B12001 B12003 B10052 B20009 D07012 4 R03000 B08023 B05021 B20001 D07013 7 R06000 B01064 B08014 B20061 B08014 B20061 B20018 D07014 2 R01000 B20019 D07015 3 R01000 D02005 B20002 D07016 2 R01000 B20020 D07017 2 R01000 B11070 D07018 13 B08016 R02000 B08017 D01012 R04000 B07006 B11001 B11002 B11041 B20009 R01000 B20001 D07014 D07020 3 D07011 D07014 D07016 D07021 9 D07011 D07012 D07013 D07014 D07015 D07016 D07017 D07018 D07015 D07030 2 B15001 B15002 D07031 7 B08022 B08023 B15001 B08023 B15001 B08023 B15002 D07041 7 D01001 B01015 D01024 D01011 D01012 D01070 D07030 D07042 9 D01001 B01015 D01024 D01011 D01012 B08021 B04025 D01070 D07031 D07043 7 D01001 B01015 D01024 D01011 D01012 D01074 D07030 D07044 9 D01001 B01015 D01024 D01011 D01012 B08021 B04025 D01074 D07031 D07060 2 B07061 B12030 D07061 3 D01031 R01005 D07060 D07062 3 D01032 R01005 D07060 D07063 2 B07061 B12130 D08001 3 D01033 D02011 B22042 D08002 3 D01034 D02011 B22042 D08003 3 D01035 D02011 B22042 D08004 3 D01036 D02011 B22042 D08005 2 D08004 D02024 D08006 8 B10004 B10061 B10063 B11001 B11002 B12004 B13003 B22042 D08007 4 D01055 D02011 B07062 B22042 D09001 3 D01037 R01000 D03011 D09002 3 D01038 R01000 D03011 D09003 3 D01037 R01000 D03012 D09004 3 D01038 R01000 D03012 D09005 4 D01037 D02004 R01000 D03013 D09006 4 D01038 D02004 R01000 D03013 D09007 4 D01037 D02004 R01000 D03014 D09008 4 D01038 D02004 R01000 D03014 D09011 3 D01039 R01000 D03011 D09012 3 D01039 R01000 D03012 D09013 4 D01039 D02004 R01000 D03013 D09014 4 D01039 D02004 R01000 D03014 D09015 3 D01040 R01000 D03011 D09016 3 D01040 R01000 D03012 D09017 4 D01040 D02004 R01000 D03013 D09018 4 D01040 D02004 R01000 D03014 D09019 4 D01031 B02003 R01000 D03011 D09020 7 D01031 B02003 R04000 B07003 B11003 B11004 B11005 D09030 7 B15004 B15005 R04000 B04015 B08006 B07004 B15003 D09040 3 D01075 D01076 D09030 D09041 4 D07041 D01075 D01076 D09030 D09042 4 D07042 D01075 D01076 D09030 D09044 4 D07044 D01075 D01076 D09030 D10001 5 D01042 D03031 D03032 R01026 D03025 D10002 5 D01042 D03031 D03032 R01009 D03023 D10003 5 D01042 D03031 D03032 R01006 D03023 D10004 5 D01042 D03031 D03032 R01003 D03024 D10005 5 D01042 D03031 D03033 R01000 D03025 D10006 5 D01042 D03031 D03033 R01000 D03023 D10007 5 D01042 D03031 D03033 R01000 D03024 D10008 8 D10011 R01019 D10012 B02150 B25079 B25080 B33032 B14045 D10009 3 D10011 R01015 D10012 D10010 3 D10011 R01005 D10012 D10014 3 D01072 D03041 D04011 D10015 13 D01072 B07024 B10002 D03041 R01003 D04032 B02152 B02024 B07004 B07004 B13003 R01003 D04033 D10016 13 D01072 B07024 B10002 D03041 R01012 D04032 B02152 B02024 B07004 B07004 B13003 R01012 D04033 D10020 6 D10022 D01011 D01013 D01021 D04034 D10021 D10022 4 B01007 B02019 B01033 B02172 D10023 17 D01072 B30021 B30022 B08012 B07024 B07025 B10002 R01012 D04032 R05002 B02152 B02024 B07004 B07004 B13003 R01012 D04033 D10050 13 D10051 D10052 R01000 D10053 R01004 D10054 B20010 D10052 R01015 D10053 D10052 R01004 D10053 D10195 3 D01250 D03250 D04250 D11001 9 D01051 B07002 B12001 B11001 B11002 B11031 B11032 B11033 B20041 D11002 4 D01065 D01066 D11003 D11004 D11003 5 B10070 B11001 B11002 B12001 B13002 D11004 12 R01000 B11034 R01000 B11035 R01000 B11075 R01000 B11076 R01000 B33025 R01000 B33026 D11005 13 B01008 B01023 D01021 D01011 D01013 B07010 B08009 B11001 B11002 B11031 B11036 B12101 B33025 D11006 6 B07010 B11001 B11002 B02064 B12101 B12103 D11193 16 D01197 D01011 D01012 D01023 B08004 B07004 B08021 B11001 B11002 B11031 B11034 B11035 B12001 B12003 B13003 B20041 D12001 2 D01043 D04001 D12002 2 D01043 D04002 D12003 2 D01042 D04003 D12004 2 D01042 D04004 D12005 2 D01042 B20014 D12006 2 D01044 D04005 D12007 2 D01042 D04006 D12010 6 B01007 B05040 B02021 B05041 B04001 B04043 D12014 8 D12010 D12011 R05056 D01023 B05042 B05052 D12012 D12013 D12016 3 D12010 D12011 D12015 D12018 3 D12010 D12011 D12017 D12020 11 D01047 D01048 B15015 B29002 B21076 R04012 B06030 R02012 B05030 B21075 B21066 D12021 6 D01047 R01003 D01049 B11012 B11011 B21067 D12022 15 D01047 B08022 B11012 B11050 B22070 B22026 D12041 B10050 B21068 B21071 B21072 B21073 D12042 B21062 B15011 D12023 7 D01047 R03003 B08022 B12061 B22050 B21069 B21085 D12024 11 D12020 B08060 B08022 B08060 B08022 B25014 B22101 B22097 B22098 B22099 B22100 D12025 11 D12019 B08060 B08022 B08060 B08022 B25014 B22101 B22097 B22098 B22099 B22100 D12026 19 D01046 D01011 D01013 D01023 D12031 R01004 D12030 B21110 D01023 D21027 B21111 D01023 D21027 B21112 D01023 D21027 B21113 D01023 D21027 D12027 9 D01047 R05009 D01023 B07021 B12061 B07021 B12061 B21085 B21070 D12031 8 B05034 B06034 B21109 B11081 B11082 B21101 B21102 B21103 D12032 4 B21120 B21121 B13055 B21122 D12033 4 B02104 B08022 B12063 B12065 D12042 6 B21077 B21078 B21079 B21080 B21081 B21082 D12045 21 B01007 B02019 B01096 B25061 B05040 D01011 D01013 D01021 B07002 B12180 B12181 B12182 B12183 B12184 B12185 B02174 B21086 B12186 B21087 B12187 B33043 D13009 3 B21001 R01000 B21001 D13010 3 B21036 R01000 B21036 D13031 4 B06002 B06012 R01000 B30001 D13032 4 B05002 B05012 R01000 D13031 D13041 9 B06002 R10000 R04000 B06012 R01000 B30001 B06012 R01000 B30001 D13042 4 B05002 B05012 R01000 D13041 D13043 11 B06002 B05002 B05012 R12000 R10000 R04000 B06012 R01000 B30001 R01000 B30001 D15001 5 B01011 D01011 D01012 D01023 D06001 D15002 5 B01011 D01011 D01012 D01023 D06004 D16001 10 D01011 B04004 D01023 B01021 B02041 B19001 B10051 B19002 B19003 B19004 D16002 15 B08021 B04001 B04002 B04003 B04004 B04005 B01033 B08021 B04001 B04002 B04003 B04004 B04005 B07002 B07002 D16003 10 R09000 B08011 B08007 R04000 B05002 B06002 B10002 B11002 B08007 B08011 D16004 11 R10000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B11031 B08007 B08011 D16005 9 R08000 B08005 B08007 B05002 B06002 B01026 B19001 B08007 B08005 D16006 12 R11000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B20011 B20012 B08007 B08011 D16007 10 R09000 B08011 B08007 R04000 B05002 B06002 B19005 B19006 B08007 B08011 D16008 11 R10000 B08001 B08007 B08023 R03000 B05002 B06002 B10002 B08023 B08007 B08001 D16009 11 R10000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B20041 B08007 B08011 D16010 8 R07000 B08011 B08007 B01022 B05002 B06002 B08007 B08011 D16011 17 R16000 B08011 B01022 B08007 R02000 B05002 B06002 B08021 B04001 B04002 B04003 B04004 B04005 B20090 B08021 B08007 B08011 D16020 5 B01023 B01025 B01027 D01011 D01012 D16021 23 D01023 B02041 B19001 B19007 B19005 B19006 B19008 B08005 B10004 B08005 B10004 B19007 B08005 B08021 B04075 B11040 B19007 R05004 B05021 B05021 R02002 B19003 B19004 D16022 23 B01032 B02041 B19001 B19010 R18000 B08021 B04014 B08005 D01023 B19005 B19006 B10004 B11041 B08021 B04075 B11040 B19008 R05004 B05021 B05021 R02002 B19003 B19004 D16026 2 D16020 D16021 D18001 2 D01025 B24011 D18003 4 D01026 B24005 B24004 B24021 D18004 6 D01025 B04023 B13011 B24005 B24004 B24022 D21001 6 B02101 B02114 B02105 B02106 B02107 B02121 D21003 4 B21051 B21014 B21017 B21030 D21004 4 D01031 B02003 R01000 D21003 D21005 12 B25004 B02121 B02122 B02123 B02124 B02125 B02126 B02127 B02128 B02129 B02130 B02131 D21006 4 B25001 B25002 B25003 B25005 D21007 8 B25009 B25010 B25011 B25012 B25013 B25015 B25016 B25017 D21008 3 B25006 B25007 B25008 D21009 2 B25018 B25019 D21010 13 B02101 B07002 B02102 B02103 B02104 B02105 B02106 B02107 B02108 B02109 B02110 B02132 B02133 D21011 3 B30031 B30032 B29002 D21012 2 R01000 B02135 D35001 4 B08035 B35001 B08036 D01001 D35002 4 B08035 B35001 B08036 B01033 D35003 6 B08021 B04001 B04002 B04003 B04004 B04073 D35004 7 B08021 B04004 B08021 B04004 B35000 D01001 B35011 D35005 7 B08021 B04004 B08021 B04004 B35000 B01001 B35011 D35006 7 B08021 B04004 B08021 B04004 B35000 B01003 B35011 D35007 9 B08021 B04004 B08021 B04004 B35000 B01001 R02000 B01002 B35011 D35010 3 D35002 D35003 D35007 dballe-7.7/tables/Makefile.am0000644000175000017500000000144712652630043013050 00000000000000## Process this file with automake to produce Makefile.in crexbtables = B990203.txt B990204.txt B000299.txt crexdtables = D990203.txt D990204.txt D000299.txt bufrbtables = B000000002001200.txt \ B000000002001400.txt \ B0000000000200014001.txt bufrdtables = D000000002001200.txt \ D000000002001400.txt \ D0000000000200014001.txt table_DATA = repinfo.csv dballe.txt $(crexbtables) $(crexdtables) $(bufrbtables) $(bufrdtables) noinst_DATA = dballe.tex dballe.tex: dballe.txt mkbdoc $(srcdir)/mkbdoc tex < $< > $@ B000000002001400.txt: dballe.txt cut -b 1-119 < $< > $@ B0000000000200014001.txt: dballe.txt cut -b 1-119 < $< > $@ B990204.txt: dballe.txt cp $< $@ B000299.txt: dballe.txt cp $< $@ EXTRA_DIST = $(table_DATA) mkbdoc distclean-local: rm -f dballe.tex dballe-7.7/tables/dballe.txt0000644000175000017500000023620212652630043012777 00000000000000 001001 WMO BLOCK NUMBER NUMERIC 0 0 7 NUMERIC 0 2 001002 WMO STATION NUMBER NUMERIC 0 0 10 NUMERIC 0 3 001006 AIRCRAFT FLIGHT NUMBER CCITTIA5 0 0 64 CHARACTER 0 8 001007 SATELLITE IDENTIFIER CODE TABLE 1007 0 0 10 CODE TABLE 1007 0 3 001008 AIRCRAFT REGISTRATION NUMBER OR OTHER IDENTIFICATION CCITTIA5 0 0 64 CHARACTER 0 8 001011 SHIP OR MOBILE LAND STATION IDENTIFIER CCITTIA5 0 0 72 CHARACTER 0 9 001012 DIRECTION OF MOTION OF MOVING OBSERVING PLATFORM** DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 001013 SPEED OF MOTION OF MOVING OBSERVING PLATFORM* M/S 0 0 10 M/S 0 3 001019 LONG STATION OR SITE NAME CCITTIA5 0 0 256 CHARACTER 0 32 001023 OBSERVATION SEQUENCE NUMBER NUMERIC 0 0 9 NUMERIC 0 3 001033 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE CODE TABLE 001033 0 0 8 CODE TABLE 001033 0 3 001034 IDENTIFICATION OF ORIGINATING/GENERATING SUB-CENTRE CODE TABLE 001034 0 0 8 CODE TABLE 001034 0 3 001063 ICAO LOCATION INDICATOR CCITTIA5 0 0 64 CHARACTER 0 8 001192 [SIM] MeteoDB station ID NUMERIC 0 0 24 NUMERIC 0 8 001193 [SIM] Report code NUMERIC 0 0 16 NUMERIC 0 5 001194 [SIM] Report mnemonic CCITTIA5 0 0 128 CHARACTER 0 16 001212 AIR QUALITY OBSERVING STATION LOCAL CODE CCITTIA5 0 0 56 CHARACTER 0 7 001213 AIRBASE AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 56 CHARACTER 0 7 001214 GEMS AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 48 CHARACTER 0 6 001215 AIR QUALITY OBSERVING STATION DOMINANT EMISSION SOURCE CODE TABLE 001215 0 0 3 CODE TABLE 001215 0 1 001216 AIR QUALITY OBSERVING STATION AREA TYPE CODE TABLE 001216 0 0 3 CODE TABLE 001216 0 1 001217 AIR QUALITY OBSERVING STATION TERRAIN TYPE CODE TABLE 001217 0 0 4 CODE TABLE 001217 0 2 002001 TYPE OF STATION CODE TABLE 2001 0 0 2 CODE TABLE 2001 0 1 002002 TYPE OF INSTRUMENTATION FOR WIND MEASUREMENT FLAG TABLE 2002 0 0 4 FLAG TABLE 2002 0 2 002003 TYPE OF MEASURING EQUIPMENT USED CODE TABLE 2003 0 0 4 CODE TABLE 2003 0 2 002004 TYPE OF INSTRUMENTATION FOR EVAPORATION MEASUREMENT OR TYPE OF C CODE TABLE 2004 0 0 4 CODE TABLE 2004 0 2 002005 PRECISION OF TEMPERATURE OBSERVATION K 2 0 7 K 2 3 002011 RADIOSONDE TYPE CODE TABLE 2011 0 0 8 CODE TABLE 2011 0 3 002012 RADIOSONDE COMPUTATIONAL METHOD CODE TABLE 2012 0 0 4 CODE TABLE 2012 0 2 002013 SOLAR AND INFRARED RADIATION CORRECTION CODE TABLE 2013 0 0 4 CODE TABLE 2013 0 2 002014 TRACKING TECHNIQUE/STATUS OF SYSTEM USED CODE TABLE 2014 0 0 7 CODE TABLE 2014 0 3 002038 METHOD OF WATER TEMPERATURE AND/OR SALINITY MEASUREMENT CODE TABLE 2038 0 0 4 CODE TABLE 2038 0 2 002039 METHOD OF WET-BULB TEMPERATURE MEASUREMENT CODE TABLE 2039 0 0 3 CODE TABLE 2039 0 1 002048 SATELLITE SENSOR INDICATOR CODE TABLE 2048 0 0 4 CODE TABLE 2048 0 2 002061 AIRCRAFT NAVIGATIONAL SYSTEM CODE TABLE 2061 0 0 3 CODE TABLE 2061 0 1 002062 TYPE OF AIRCRAFT DATA RELAY SYSTEM CODE TABLE 2062 0 0 4 CODE TABLE 2062 0 2 002063 AIRCRAFT ROLL ANGLE DEGREE 2 -18000 16 DEGREE 2 5 002064 AIRCRAFT ROLL ANGLE QUALITY CODE TABLE 2064 0 0 2 CODE TABLE 2064 0 1 002070 ORIGINAL SPECIFICATION OF LATITUDE/LONGITUDE CODE TABLE 2070 0 0 4 CODE TABLE 2070 0 2 002121 MEAN FREQUENCY Hz -8 0 7 Hz -8 3 002125 PULSE REPETITION FREQUENCY Hz -1 0 8 Hz -1 3 004001 YEAR YEAR 0 0 12 YEAR 0 4 004002 MONTH MONTH 0 0 4 MONTH 0 2 004003 DAY DAY 0 0 6 DAY 0 2 004004 HOUR HOUR 0 0 5 HOUR 0 2 004005 MINUTE MINUTE 0 0 6 MINUTE 0 2 004006 SECOND SECOND 0 0 6 SECOND 0 2 004086 LONG TIME PERIOD OR DISPLACEMENT SECOND 0 -8192 15 SECOND 0 5 004192 [SIM] Time range type NUMERIC 0 0 10 NUMERIC 0 4 004193 [SIM] Time range P1 NUMERIC 0 -536870912 31 NUMERIC 0 10 004194 [SIM] Time range P2 NUMERIC 0 -536870912 31 NUMERIC 0 10 004195 [SIM] Temperature event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 004196 [SIM] Relative humidity event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 004197 [SIM] Wind velocity event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 004198 [SIM] Pressure event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 005001 LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 005015 LATITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 005021 BEARING OR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005022 SOLAR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005040 ORBIT NUMBER NUMERIC 0 0 24 NUMERIC 0 8 005041 SCAN LINE NUMBER NUMERIC 0 0 8 NUMERIC 0 3 005043 FIELD OF VIEW NUMBER NUMERIC 0 0 8 NUMERIC 0 3 006001 LONGITUDE (HIGH ACCURACY) DEGREE 5 -18000000 26 DEGREE 5 8 006015 LONGITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -18000000 26 DEGREE 5 8 007002 HEIGHT OR ALTITUDE M -1 -40 16 M -1 5 007004 PRESSURE PA -1 0 14 PA -1 5 007007 HEIGHT M 0 -1000 17 M 0 6 007010 FLIGHT LEVEL M 0 -1024 16 FT -1 5 007024 SATELLITE ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007025 SOLAR ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007030 HEIGHT OF STATION GROUND ABOVE MEAN SEA LEVEL (SEE NOTE 3) M 1 -4000 17 M 1 5 007031 HEIGHT OF BAROMETER ABOVE MEAN SEA LEVEL (SEE NOTE 4) M 1 - 4000 17 M 1 5 007032 HEIGHT OF SENSOR ABOVE LOCAL GROUND (OR DECK OF MARINE PLATFORM) M 2 0 16 M 2 5 007192 [SIM] First level type NUMERIC 0 0 10 NUMERIC 0 4 007193 [SIM] Level L1 NUMERIC 0 -536870912 31 NUMERIC 0 10 007194 [SIM] Level L2 NUMERIC 0 -536870912 31 NUMERIC 0 10 007195 [SIM] Second level type NUMERIC 0 0 31 NUMERIC 0 4 008002 VERTICAL SIGNIFICANCE (SURFACE OBSERVATIONS) CODE TABLE 8002 0 0 6 CODE TABLE 8002 0 2 008004 PHASE OF AIRCRAFT FLIGHT CODE TABLE 8004 0 0 3 CODE TABLE 8004 0 1 008009 DETAILED PHASE OF FLIGHT CODE TABLE 8009 0 0 4 CODE TABLE 8009 0 2 008021 TIME SIGNIFICANCE CODE TABLE 8021 0 0 5 CODE TABLE 8021 0 2 008042 EXTENDED VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8042 0 0 18 FLAG TABLE 8042 0 6 008044 (VAL) CAS REGISTRY NUMBER CCITTIA5 0 0 88 CHARACTER 0 11 008192 [SIM] Number of wind velocity mean values present NUMERIC 0 0 5 NUMERIC 0 2 008193 [SIM] Number of wind velocity minimum values present NUMERIC 0 0 5 NUMERIC 0 2 008194 [SIM] Number of wind velocity maximum values present NUMERIC 0 0 5 NUMERIC 0 2 008195 [SIM] Number of wind prevalent direction values present NUMERIC 0 0 5 NUMERIC 0 2 008196 [SIM] Number of mean temperature values present NUMERIC 0 0 5 NUMERIC 0 2 008197 [SIM] Number of minimum temperature values present NUMERIC 0 0 5 NUMERIC 0 2 008198 [SIM] Number of maximum temperature values present NUMERIC 0 0 5 NUMERIC 0 2 008199 [SIM] Number of mean relative humidity values present NUMERIC 0 0 5 NUMERIC 0 2 008200 [SIM] Number of minimum relative humidity values present NUMERIC 0 0 5 NUMERIC 0 2 008201 [SIM] Number of maximum relative humidity values present NUMERIC 0 0 5 NUMERIC 0 2 008202 [SIM] Number of mean pressure values present NUMERIC 0 0 5 NUMERIC 0 2 008203 [SIM] Number of minimum pressure values present NUMERIC 0 0 5 NUMERIC 0 2 008204 [SIM] Number of maximum pressure values present NUMERIC 0 0 5 NUMERIC 0 2 008205 [SIM] Number of precipitation values present NUMERIC 0 0 5 NUMERIC 0 2 008206 [SIM] Number of leaf wetness values present NUMERIC 0 0 5 NUMERIC 0 2 008207 [SIM] Number of scalar wind velocity mean values present NUMERIC 0 0 5 NUMERIC 0 2 008208 [SIM] Number of cloud cover mean values present NUMERIC 0 0 5 NUMERIC 0 2 008209 [SIM] Number of cloud cover maximum values present NUMERIC 0 0 5 NUMERIC 0 2 008210 [SIM] Number of cloud cover minimum values present NUMERIC 0 0 5 NUMERIC 0 2 010004 PRESSURE PA -1 0 14 PA -1 5 010007 HEIGHT M 0 -1000 17 M 0 6 010008 GEOPOTENTIAL M**2/S**2 0 -10000 20 M**2/S**2 0 7 010009 GEOPOTENTIAL HEIGHT GPM 0 -1000 17 GPM 0 5 010051 PRESSURE REDUCED TO MEAN SEA LEVEL PA -1 0 14 PA -1 5 010052 ALTIMETER SETTING (QNH) PA -1 0 14 PA -1 5 010060 PRESSURE CHANGE PA -1 -1024 11 PA -1 4 010063 CHARACTERISTIC OF PRESSURE TENDENCY CODE TABLE 10063 0 0 4 CODE TABLE 10063 0 2 010197 ANEMOMETER HEIGHT M 0 0 9 M 0 3 011001 WIND DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011002 WIND SPEED M/S 1 0 12 M/S 1 4 011003 U-COMPONENT M/S 1 -4096 13 M/S 1 4 011004 V-COMPONENT M/S 1 -4096 13 M/S 1 4 011005 W-COMPONENT PA/S 1 -512 10 PA/S 1 4 011006 W-COMPONENT M/S 2 -4096 13 M/S 2 4 011016 EXTREME COUNTERCLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011017 EXTREME CLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011031 DEGREE OF TURBULENCE CODE TABLE 11031 0 0 4 CODE TABLE 11031 0 2 011036 MAXIMUM DERIVED EQUIVALENT VERTICAL GUST SPEED M/S 1 0 10 M/S 1 4 011037 TURBULENCE INDEX CODE TABLE 11037 0 0 6 CODE TABLE 11037 0 2 011039 EXTENDED TIME OF OCCURRENCE OF PEAK EDDY DISSIPATION RATE CODE TABLE 11039 0 0 6 CODE TABLE 11039 0 2 011041 MAXIMUM WIND GUST SPEED M/S 1 0 12 M/S 1 4 011043 MAXIMUM WIND GUST DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011050 STANDARD DEVIATION OF HORIZONTAL WIND SPEED M/S 1 0 12 M/S 1 4 011061 ABSOLUTE WIND SHEAR IN 1 KM LAYER BELOW M/S 1 0 12 M/S 1 4 011062 ABSOLUTE WIND SHEAR IN 1 KM LAYER ABOVE M/S 1 0 12 M/S 1 4 011075 MEAN TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 M**(2/3)/S 2 3 011076 PEAK TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 M**(2/3)/S 2 3 011077 REPORTING INTERVAL OR AVERAGING TIME FOR EDDY DISSIPATION RATE S 0 0 12 S 0 4 011192 [SIM] W-component terrain following M/S 2 -4096 13 M/S 2 4 011193 [SIM] Stability class NUMERIC 0 0 4 NUMERIC 0 2 011194 [SIM] Friction velocity (calmet) M/S 3 0 14 M/S 3 4 011195 [SIM] Mixing height (calmet) M 0 0 12 M 0 4 011196 [SIM] Obukov lenght (calmet) M 1 -100000 15 M 1 5 011197 [SIM] Convective velocitiy scale (calmet) M/S 3 0 14 M/S 3 4 011198 [SIM] SQRT(2*TKE) M/S 4 0 20 M/S 4 6 011199 [SIM] Surface Roughness M 3 0 14 M 1 4 011200 [SIM] U-component of momentum flux N/M**2 4 -524288 20 N/M**2 4 6 011201 [SIM] V-component of momentum flux N/M**2 4 -524288 20 N/M**2 4 6 011202 [SIM] Friction velocity (diagmet) M/S 3 0 14 M/S 3 4 011203 [SIM] Mixing height (diagmet) M 0 0 12 M 0 4 011204 [SIM] Obukov lenght (diagmet) M 1 -100000 15 M 1 5 011205 [SIM] Convective velocitiy scale (diagmet) M/S 3 0 14 M/S 3 4 011206 [SIM] Friction velocity (COSMO) M/S 3 0 14 M/S 3 4 011207 [SIM] Obukov lenght (COSMO) M 1 -100000 15 M 1 5 011208 [SIM] Distance covered by the hourly mean wind M 0 0 23 M 0 7 012001 TEMPERATURE/AIR TEMPERATURE K 1 0 12 C 1 3 012003 DEW-POINT TEMPERATURE K 1 0 12 C 1 3 012030 SOIL TEMPERATURE K 1 0 12 C 1 3 012049 Temperature change over specified period K 0 -30 6 C 0 2 012061 SKIN TEMPERATURE K 1 0 12 K 1 4 012063 BRIGHTNESS TEMPERATURE K 1 0 12 K 1 4 012101 TEMPERATURE/DRY-BULB TEMPERATURE K 2 0 16 K 2 5 012102 WET-BULB TEMPERATURE K 2 0 16 C 2 4 012103 DEW-POINT TEMPERATURE K 2 0 16 K 2 5 012121 GROUND MINIMUM TEMPERATURE K 2 0 16 C 2 4 012131 SNOW TEMPERATURE K 2 0 16 C 2 4 012192 POTENTIAL TEMPERATURE K 2 0 16 K 2 5 012193 PSEUDO-EQUIVALENT POTENTIAL TEMPERATURE K 2 0 16 K 2 5 012194 [SIM] Air density KG/M**3 6 0 20 KG/M**3 6 6 013001 SPECIFIC HUMIDITY KG/KG 5 0 14 KG/KG 5 5 013002 MIXING RATIO KG/KG 5 0 14 KG/KG 5 5 013003 RELATIVE HUMIDITY % 0 0 7 % 0 3 013011 TOTAL PRECIPITATION / TOTAL WATER EQUIVALENT KG/M**2 1 -1 14 KG/M**2 1 5 013012 DEPTH OF FRESH SNOW M 2 -2 12 M 2 4 013013 TOTAL SNOW DEPTH M 3 -20 20 M 3 6 013031 EVAPOTRANSPIRATION KG/M**2 1 0 7 KG/M**2 0 3 013033 EVAPORATION/EVAPOTRANSPIRATION KG/M**2 1 0 10 KG/M**2 1 4 013081 WATER CONDUCTIVITY S/M 3 0 14 S/M 3 4 013082 WATER TEMPERATURE K 1 0 12 K 1 4 013192 [SIM] Cloud liquid water content KG/KG 8 0 27 KG/KG 8 8 013193 [SIM] Cloud ice content KG/KG 8 0 27 KG/KG 8 8 013194 [SIM] Water table depth M 3 0 18 M 3 6 013195 [SIM] Precipitating liquid water KG/KG 8 0 27 KG/KG 8 8 013196 [SIM] Precipitating ice KG/KG 8 0 27 KG/KG 8 8 013197 [SIM] Total precipitating water+ice KG/KG 8 0 27 KG/KG 8 8 013198 [SIM] Total liquid water (cloud+precipitating) KG/KG 8 0 27 KG/KG 8 8 013199 [SIM] Total ice (cloud+precipitating) KG/KG 8 0 27 KG/KG 8 8 013200 [SIM] Grid-scale liquid precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013201 [SIM] Grid-scale snowfall KG/M**2 1 -1 14 KG/M**2 1 5 013202 [SIM] Convective liquid precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013203 [SIM] Convective snowfall KG/M**2 1 -1 14 KG/M**2 1 5 013204 [SIM] Total convective precipitation (liquid + snow) KG/M**2 1 -1 14 KG/M**2 1 5 013205 [SIM] Snowfall (grid-scale + convective) KG/M**2 1 -1 14 KG/M**2 1 5 013206 [SIM] Soil water content KG/M**2 1 0 14 KG/M**2 1 5 013210 [SIM] Penetration of the probe in the snow M 2 0 9 M 2 3 013212 [SIM] Leaf wetness duration S -1 0 24 S -1 7 013215 [SIM] River level M 2 -100000 18 M 2 6 013216 [SIM] Hourly precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013217 [SIM] 5 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013218 [SIM] 10 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013219 [SIM] 15 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013220 [SIM] 20 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013221 [SIM] 30 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013222 [SIM] 180 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013223 [SIM] 360 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013224 [SIM] 720 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013225 [SIM] 1440 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013226 [SIM] River discharge M**3/S 2 0 21 M**3/S 2 7 013227 [SIM] Soil volumetric water content % 1 0 10 % 1 4 013228 [SIM] Piezometric level M 3 0 18 M 3 6 013229 [SIM] Density of snow KG/M**3 1 0 14 KG/M**3 1 5 013230 [SIM] Convective Available Potential Energy (CAPE) J/KG 1 0 17 J/KG 1 5 014002 Long-wave radiation, integrated over period specified J M-2 -3 -65536 17 J M-2 -3 5 014004 Short-wave radiation, integrated over period specified J M-2 -3 -65536 17 J M-2 -3 5 014016 NET RADIATION J/M**2 -4 -16384 15 J/M**2 -4 5 014017 INSTANTANEOUS LONG-WAVE RADIATION (incoming) W/M**2 0 -2048 12 W/M**2 0 4 014018 INSTANTANEOUS SHORT-WAVE RADIATION (incoming) W/M**2 0 -2048 12 W/M**2 -3 4 014019 SURFACE ALBEDO % 0 0 7 % 0 3 014021 GLOBAL SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 J/M**2 -4 5 014028 Global solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 J M-2 -2 6 014029 Diffuse solar radiation (high accuracy), integrated over period J M-2 -2 0 20 J M-2 -2 6 014030 Direct solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 J M-2 -2 6 014031 TOTAL SUNSHINE MINUTE 0 0 11 MINUTE 0 4 014192 [SIM] Instantenous sensible heat flux W/m**2 0 -1024 11 W/M**2 0 4 014193 [SIM] Instantenous latent heat flux W/m**2 0 -1024 11 W/M**2 0 4 014194 [SIM] Instantenous direct solar radiation W/M**2 0 -2048 12 W/M**2 -3 4 014195 [SIM] Instantenous diffuse solar radiation W/M**2 0 -2048 12 W/M**2 -3 4 014196 [SIM] INSTANTANEOUS NET LONG-WAVE RADIATION W/M**2 0 -2048 12 W/M**2 0 4 014197 [SIM] INSTANTANEOUS NET SHORT-WAVE RADIATION W/M**2 0 -2048 12 W/M**2 -3 4 014198 [SIM] Visible radiation (downward) W/M**2 3 -50000 21 W/M**2 3 7 014199 [SIM] Visible radiation (upward) W/M**2 3 -50000 21 W/M**2 3 7 014200 [SIM] Infrared radiation (downward) W/M**2 3 0 20 W/M**2 3 7 014201 [SIM] Infrared radiation (upward) W/M**2 3 0 20 W/M**2 3 7 015192 [SIM] NO Concentration KG/M**3 10 0 20 KG/M**3 10 6 015193 [SIM] NO2 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015194 [SIM] O3 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015195 [SIM] PM10 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015196 [SIM] CO Concentration KG/M**3 10 0 20 KG/M**3 10 6 015197 [SIM] SO2 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015198 [SIM] PM2.5 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015199 [SIM] NOY Concentration KG/M**3 10 0 20 KG/M**3 10 6 015200 [SIM] HCNM Concentration KG/M**3 10 0 20 KG/M**3 10 6 015201 [SIM] ALDE Concentration KG/M**3 10 0 20 KG/M**3 10 6 015202 [SIM] PM5 Concentration (tot. aerosol < 5 ug) KG/M**3 10 0 20 KG/M**3 10 6 015203 [SIM] PM1 Concentration (tot. aerosol < 1.25 ug) KG/M**3 10 0 20 KG/M**3 10 6 015204 [SIM] PM06 Concentration (tot. aerosol < 0.6 ug) KG/M**3 10 0 20 KG/M**3 10 6 015205 [SIM] PM03 Concentration (tot. aerosol < 0.3 ug) KG/M**3 10 0 20 KG/M**3 10 6 015206 [SIM] PM015 Concentration (tot. aerosol < 0.15 ug) KG/M**3 10 0 20 KG/M**3 10 6 015207 [SIM] PM008 Concentration (tot. aerosol < 0.08 ug) KG/M**3 10 0 20 KG/M**3 10 6 015208 [SIM] Concentration of primary particulate matter in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015209 [SIM] Concentration of sulfate in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015210 [SIM] Concentration of nitrate in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015211 [SIM] Concentration of ammonium in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015212 [SIM] Concentration of black carbon in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015213 [SIM] Concentration of organic carbon in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015214 [SIM] Concentration of dust in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015215 [SIM] Concentration of anthrop. A1D in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015216 [SIM] Concentration of anthrop. BmP in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015217 [SIM] Concentration of biogenic A1D in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015218 [SIM] Concentration of biogenic BmP in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015219 [SIM] Concentration of water in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015220 [SIM] Concentration of sea salt in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015221 [SIM] Concentration of secondary organic aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015222 [SIM] Total concentration of primary aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015223 [SIM] Total concentration of secondary aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015224 [SIM] Uncertainity in O3 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015225 [SIM] Uncertainity in PM10 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015226 [SIM] Uncertainity in NO2 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015227 [SIM] Uncertainity in PM2.5 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015228 [SIM] NH3 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015229 [SIM] Concentration of primary part. matter in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015230 [SIM] Concentration of sulfate in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015231 [SIM] Concentration of nitrate in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015232 [SIM] Concentration of ammonium in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015233 [SIM] Concentration of anthrop. sec. org. in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015234 [SIM] Concentration of biogenic sec. org. in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015235 [SIM] Concentration of ISOPA1 in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015236 [SIM] C6H6 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015237 [SIM] Concentration of anthropogenic aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015238 [SIM] Concentration of biogenic aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015239 [SIM] Concentration of anthropogenic aerosol in PM2.5 KG/M**3 10 0 20 KG/M**3 10 6 015240 [SIM] Concentration of biogenic aerosol in PM2.5 KG/M**3 10 0 20 KG/M**3 10 6 015241 [SIM] Aerosol Optical Thickness NUMERIC 4 0 15 NUMERIC 4 5 020001 HORIZONTAL VISIBILITY M -1 0 13 M -1 4 020003 PRESENT WEATHER (SEE NOTE 1) CODE TABLE 20003 0 0 9 CODE TABLE 20003 0 3 020004 PAST WEATHER (1) (SEE NOTE 2) CODE TABLE 20004 0 0 5 CODE TABLE 20004 0 2 020005 PAST WEATHER (2) (SEE NOTE 2) CODE TABLE 20005 0 0 5 CODE TABLE 20005 0 2 020009 GENERAL WEATHER INDICATOR (TAF/METAR) CODE TABLE 20009 0 0 4 CODE TABLE 20009 0 2 020010 CLOUD COVER (TOTAL) % 0 0 7 % 0 3 020011 CLOUD AMOUNT CODE TABLE 20011 0 0 4 CODE TABLE 20011 0 2 020012 CLOUD TYPE CODE TABLE 20012 0 0 6 CODE TABLE 20012 0 2 020013 HEIGHT OF BASE OF CLOUD M 0 -400 17 M 0 5 020017 CLOUD TOP DESCRIPTION CODE TABLE 20017 0 0 4 CODE TABLE 20017 0 2 020019 SIGNIFICANT PRESENT OR FORECAST WEATHER CCITTIA5 0 0 72 CHARACTER 0 9 020021 TYPE OF PRECIPITATION FLAG TABLE 20021 0 0 30 FLAG TABLE 20021 0 10 020031 ICE DEPOSIT (THICKNESS) M 2 0 7 M 2 3 020032 RATE OF ICE ACCRETION CODE TABLE 20032 0 0 3 CODE TABLE 20032 0 1 020033 CAUSE OF ICE ACCRETION FLAG TABLE 20033 0 0 4 FLAG TABLE 20033 0 2 020034 SEA ICE CONCENTRATION CODE TABLE 20034 0 0 5 CODE TABLE 20034 0 2 020035 AMOUNT AND TYPE OF ICE CODE TABLE 20035 0 0 4 CODE TABLE 20035 0 2 020036 ICE SITUATION CODE TABLE 20036 0 0 5 CODE TABLE 20036 0 2 020037 ICE DEVELOPMENT CODE TABLE 20037 0 0 5 CODE TABLE 20037 0 2 020038 BEARING OF ICE EDGE (SEE NOTE 3) DEGREE TRUE 0 0 12 DEGREE TRUE 0 3 020042 AIRFRAME ICING PRESENT CODE TABLE 20042 0 0 2 CODE TABLE 20042 0 1 020043 PEAK LIQUID WATER CONTENT KG/M**3 4 0 7 KG/M**3 4 2 020044 AVERAGE LIQUID WATER CONTENT KG/M**3 4 0 7 KG/M**3 4 2 020045 SUPERCOOLED LARGE DROPLET (SLD) CONDITIONS CODE TABLE 20045 0 0 2 CODE TABLE 20045 0 2 020062 STATE OF THE GROUND (WITH OR WITHOUT SNOW) CODE TABLE 20062 0 0 5 CODE TABLE 20062 0 2 020192 [SIM] Presence of rain > 1mm BOOLEAN 0 0 1 BOOLEAN 0 1 020193 [SIM] Cloud type (METAR) CCITTIA5 0 0 16 CHARACTER 0 2 020194 [SIM] Presence of shower BOOLEAN 0 0 1 BOOLEAN 0 1 020195 [SIM] Presence of hail BOOLEAN 0 0 1 BOOLEAN 0 1 020196 [SIM] Presence of thunderstorm BOOLEAN 0 0 1 BOOLEAN 0 1 020197 [SIM] Presence of snow BOOLEAN 0 0 1 BOOLEAN 0 1 020198 [SIM] Presence of frost BOOLEAN 0 0 1 BOOLEAN 0 1 020199 [SIM] Presence of dew BOOLEAN 0 0 1 BOOLEAN 0 1 020200 [SIM] Presence of fog BOOLEAN 0 0 1 BOOLEAN 0 1 020201 [SIM] Presence of water-spout BOOLEAN 0 0 1 BOOLEAN 0 1 020202 [SIM] State of the ground with snow CODE TABLE 0 0 5 CODE TABLE 0 2 022001 DIRECTION OF WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022002 DIRECTION OF WIND WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022003 DIRECTION OF SWELL WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022004 DIRECTION OF CURRENT DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022011 PERIOD OF WAVES S 0 0 6 S 0 2 022012 PERIOD OF WIND WAVES S 0 0 6 S 0 2 022013 PERIOD OF SWELL WAVES S 0 0 6 S 0 2 022021 HEIGHT OF WAVES M 1 0 10 M 1 4 022022 HEIGHT OF WIND WAVES M 1 0 10 M 1 4 022023 HEIGHT OF SWELL WAVES M 1 0 10 M 1 4 022031 SPEED OF CURRENT M/S 2 0 13 M/S 2 4 022032 SPEED OF SEA SURFACE CURRENT M/S 2 0 13 M/S 2 4 022037 Tidal elevation with respect to national land datum M 3 -10000 15 M 3 5 022038 Tidal elevation with respect to local chart datum M 3 -10000 15 M 3 5 022042 SEA/WATER TEMPERATURE K 1 0 12 K 1 4 022043 SEA/WATER TEMPERATURE K 2 0 15 K 2 5 022049 SEA-SURFACE TEMPERATURE K 2 0 15 K 2 5 022070 SIGNIFICANT WAVE HEIGHT M 2 0 13 M 2 4 022071 SPECTRAL PEAK WAVE PERIOD S 1 0 9 S 1 3 022074 AVERAGE WAVE PERIOD S 1 0 9 S 1 3 022192 [SIM] Current X component M/S 2 0 13 M/S 2 4 022193 [SIM] Current Y component M/S 2 0 13 M/S 2 4 023192 [SIM] Dry deposition of H2SO4 MOL/M**2 5 0 20 MOL/M**3 5 6 023193 [SIM] Wet deposition of H2SO4 MOL/M**2 5 0 20 MOL/M**3 5 6 023194 [SIM] Dry deposition of NH4 MOL/M**2 5 0 20 MOL/M**3 5 6 023195 [SIM] Wet deposition of NH4 MOL/M**2 5 0 20 MOL/M**3 5 6 023196 [SIM] Dry deposition of HNO3 MOL/M**2 5 0 20 MOL/M**3 5 6 023197 [SIM] Wet deposition of HNO3 MOL/M**2 5 0 20 MOL/M**3 5 6 023198 [SIM] Solid transport by river KG/S 2 0 24 KG/S 2 8 025076 LOG-10 OF (TEMP-RAD CENTRAL WAVENUMBER) FOR ATOVS LOGM-1 8 0 30 LOGM-1 8 10 029192 [SIM] Land fraction % 1 0 10 % 1 4 031000 SHORT DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 1 NUMERIC 0 1 031001 DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031011 DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031012 EXTENDED DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031021 ASSOCIATED FIELD SIGNIFICANCE CODE TABLE 31021 0 0 6 CODE TABLE 31021 0 2 031031 DATA PRESENT INDICATOR FLAG TABLE 31031 0 0 1 FLAG TABLE 31031 0 1 033002 QUALITY INFORMATION CODE TABLE 33002 0 0 2 CODE TABLE 33002 0 1 033003 QUALITY INFORMATION CODE TABLE 33003 0 0 3 CODE TABLE 33003 0 1 033005 QUALITY INFORMATION (AWS DATA) FLAG TABLE 33005 0 0 30 FLAG TABLE 33005 0 10 033006 INTERNAL MEASUREMENT STATUS INFORMATION (AWS) CODE TABLE 33006 0 0 3 CODE TABLE 33006 0 1 033007 PER CENT CONFIDENCE % 0 0 7 % 0 3 033015 DATA QUALITY CHECK INDICATOR CODE TABLE 33015 0 0 6 CODE TABLE 33015 0 2 033020 QUALITY CONTROL INDICATION OF FOLLOWING VALUE CODE TABLE 33020 0 0 3 CODE TABLE 33020 0 1 033021 QUALITY OF FOLLOWING VALUE CODE TABLE 33021 0 0 2 CODE TABLE 33021 0 1 033022 QUALITY OF BUOY SATELLITE TRANSMISSION CODE TABLE 33022 0 0 2 CODE TABLE 33022 0 1 033023 QUALITY OF BUOY LOCATION CODE TABLE 33023 0 0 2 CODE TABLE 33023 0 1 033024 STATION ELEVATION QUALITY MARK (FOR MOBILE STATIONS) CODE TABLE 33024 0 0 4 CODE TABLE 33024 0 2 033025 ACARS INTERPOLATED VALUES CODE TABLE 33025 0 0 3 CODE TABLE 33025 0 1 033026 MOISTURE QUALITY CODE TABLE 33026 0 0 6 CODE TABLE 33026 0 2 033027 LOCATION QUALITY CLASS (RANGE OF RADIUS OF 66 % CONFIDENCE) CODE TABLE 33027 0 0 3 CODE TABLE 33027 0 1 033030 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 33030 0 0 24 FLAG TABLE 33030 0 8 033031 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 33031 0 0 24 FLAG TABLE 33031 0 8 033032 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 33032 0 0 24 FLAG TABLE 33032 0 8 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS FLAG TABLE 33033 0 0 24 FLAG TABLE 33033 0 8 033035 MANUAL/AUTOMATIC QUALITY CONTROL CODE TABLE 33035 0 0 4 CODE TABLE 33035 0 2 033036 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 % 0 3 033037 WIND CORRELATION ERROR FLAG TABLE 33037 0 0 20 FLAG TABLE 33037 0 7 033038 QUALITY FLAGS FOR GROUND-BASED GNSS DATA FLAG TABLE 33038 0 0 10 FLAG TABLE 33038 0 4 033040 CONFIDENCE INTERVAL % 0 0 7 PERCENT 0 3 033041 ATTRIBUTE OF FOLLOWING VALUE CODE TABLE 33041 0 0 2 CODE TABLE 33041 0 1 033050 GLOBAL GTSPP QUALITY FLAG CODE TABLE 33050 0 0 4 CODE TABLE 33050 0 2 033192 [SIM] Climatological and consistency check % 0 0 7 PERCENT 0 3 033193 [SIM] Time consistency % 0 0 7 PERCENT 0 3 033194 [SIM] Space consistency % 0 0 7 PERCENT 0 3 033195 [SIM] MeteoDB variable ID NUMERIC 0 0 24 NUMERIC 0 8 033196 [SIM] Data has been invalidated CODE TABLE 33196 0 0 2 CODE TABLE 33196 0 1 033197 [SIM] Manual replacement in substitution CODE TABLE 33197 0 0 2 CODE TABLE 33197 0 1 033198 [SIM] Observation increment NUMERIC 4 -1073741823 31 NUMERIC 4 10 033201 [SIM] Kalman coefficient, state vector (s.v.) x1 NUMERIC 4 -1073741823 31 NUMERIC 4 10 033202 [SIM] Kalman coefficient, state vector (s.v.) x2 NUMERIC 4 -1073741823 31 NUMERIC 4 10 033203 [SIM] Kalman coefficient, s.v. error covariance matrix(1,1) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033204 [SIM] Kalman coefficient, s.v. error covariance matrix(1,2) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033205 [SIM] Kalman coefficient, s.v. error covariance matrix(2,1) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033206 [SIM] Kalman coefficient, s.v. error covariance matrix(2,2) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033207 [SIM] Kalman observation sequential counter NUMERIC 0 -127 8 NUMERIC 0 3 033208 [SIM] Kalman osservation missing counter NUMERIC 0 -127 8 NUMERIC 0 3 033209 [SIM] Normalized Density Index % 0 0 7 PERCENT 0 3 048001 [SIM] Graminacee_Graminacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048002 [SIM] Betulacee_Ontano nero POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048003 [SIM] Betulacee_Betulla POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048004 [SIM] Betulacee_Betulacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048005 [SIM] Composite_Ambrosia POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048006 [SIM] Composite_Artemisia POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048007 [SIM] Composite_Composite indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048008 [SIM] Corilacee_Nocciolo POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048009 [SIM] Corilacee_Carpino bianco -Carpino nero POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048010 [SIM] Corilacee_Corilacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048011 [SIM] Fagacee_Castagno POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048012 [SIM] Fagacee_Faggio POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048013 [SIM] Fagacee_Quercia POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048014 [SIM] Fagacee_Fagacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048015 [SIM] Oleacee_Olivo POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048016 [SIM] Oleacee_Frassino POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048017 [SIM] Oleacee_Oleacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048018 [SIM] Plantaginacee_Plantaginacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048019 [SIM] Urticacee_Urticacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048020 [SIM] Cupressacee - Taxacee indistinte_Cipresso comune POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048021 [SIM] Cupressacee - Taxacee indistinte_Cupressacee - Taxacee ind POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048022 [SIM] Chenopodiacee - Amarantacee Indistinte_Amaranto POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048023 [SIM] Chenopodiacee - Amarantacee Indistinte_Chenopodiacee - Ama POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048024 [SIM] Poligonacee_Poligonacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048025 [SIM] Euphorbiacee_Euforbiacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048026 [SIM] Mirtacee_Mirtacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048027 [SIM] Ulmacee_Bagolaro comune POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048028 [SIM] Ulmacee_Olmo campestre POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048029 [SIM] Ulmacee_Ulmacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048030 [SIM] Platanacee_Platanacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048031 [SIM] Aceraceae_Aceracee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048032 [SIM] Pinacee_Pinacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048033 [SIM] Salicacee_Salice comune POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048034 [SIM] Salicacee_Pioppo POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048035 [SIM] Salicacee_Salicacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048036 [SIM] Ciperacee_Ciperacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048037 [SIM] Juglandacee_Juglandacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048038 [SIM] Ippocastanacee_Ippocastanacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048039 [SIM] Spore fungine_Alternaria POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048040 [SIM] Spore fungine_Botrytis POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048041 [SIM] Spore fungine_Stemphylium POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048042 [SIM] Spore fungine_Cladosporium POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048043 [SIM] Spore fungine_Epicoccum POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048044 [SIM] Altri Pollini / Non Identificati_Altri pollini identificat POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048045 [SIM] Altri Pollini / Non Identificati_Pollini non identificati POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048046 [SIM] Altre Spore / Non identificati_Altre spore fungine POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048047 [SIM] Altre Spore / Non identificati_Spore fungine non identific POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048048 [SIM] Graminacee_Graminacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048049 [SIM] Plantaginacee_Plantaginacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048050 [SIM] Urticacee_Urticacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048051 [SIM] Poligonacee_Poligonacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048052 [SIM] Euphorbiacee_Euforbiacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048053 [SIM] Mirtacee_Mirtacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048054 [SIM] Platanacee_Platanacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048055 [SIM] Aceraceae_Aceracee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048056 [SIM] Pinacee_Pinacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048057 [SIM] Ciperacee_Ciperacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048058 [SIM] Juglandacee_Juglandacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048059 [SIM] Ippocastanacee_Ippocastanacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048060 [SIM] Oleacee_Ligustro POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048128 [SIM] Conta Graminacee_Graminacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048129 [SIM] Conta Betulacee_Ontano nero NUMERIC 0 0 20 NUMERIC 0 7 048130 [SIM] Conta Betulacee_Betulla NUMERIC 0 0 20 NUMERIC 0 7 048131 [SIM] Conta Betulacee_Betulacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048132 [SIM] Conta Composite_Ambrosia NUMERIC 0 0 20 NUMERIC 0 7 048133 [SIM] Conta Composite_Artemisia NUMERIC 0 0 20 NUMERIC 0 7 048134 [SIM] Conta Composite_Composite indistinte NUMERIC 0 0 20 NUMERIC 0 7 048135 [SIM] Conta Corilacee_Nocciolo NUMERIC 0 0 20 NUMERIC 0 7 048136 [SIM] Conta Corilacee_Carpino bianco -Carpino nero NUMERIC 0 0 20 NUMERIC 0 7 048137 [SIM] Conta Corilacee_Corilacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048138 [SIM] Conta Fagacee_Castagno NUMERIC 0 0 20 NUMERIC 0 7 048139 [SIM] Conta Fagacee_Faggio NUMERIC 0 0 20 NUMERIC 0 7 048140 [SIM] Conta Fagacee_Quercia NUMERIC 0 0 20 NUMERIC 0 7 048141 [SIM] Conta Fagacee_Fagacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048142 [SIM] Conta Oleacee_Olivo NUMERIC 0 0 20 NUMERIC 0 7 048143 [SIM] Conta Oleacee_Frassino NUMERIC 0 0 20 NUMERIC 0 7 048144 [SIM] Conta Oleacee_Oleacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048145 [SIM] Conta Plantaginacee_Plantaginacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048146 [SIM] Conta Urticacee_Urticacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048147 [SIM] Conta Cupressacee - Taxacee indistinte_Cipresso comune NUMERIC 0 0 20 NUMERIC 0 7 048148 [SIM] Conta Cupressacee - Taxacee indistinte_Cupressacee - Taxac NUMERIC 0 0 20 NUMERIC 0 7 048149 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Amaranto NUMERIC 0 0 20 NUMERIC 0 7 048150 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Chenopodiacee NUMERIC 0 0 20 NUMERIC 0 7 048151 [SIM] Conta Poligonacee_Poligonacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048152 [SIM] Conta Euphorbiacee_Euforbiacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048153 [SIM] Conta Mirtacee_Mirtacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048154 [SIM] Conta Ulmacee_Bagolaro comune NUMERIC 0 0 20 NUMERIC 0 7 048155 [SIM] Conta Ulmacee_Olmo campestre NUMERIC 0 0 20 NUMERIC 0 7 048156 [SIM] Conta Ulmacee_Ulmacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048157 [SIM] Conta Platanacee_Platanacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048158 [SIM] Conta Aceraceae_Aceracee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048159 [SIM] Conta Pinacee_Pinacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048160 [SIM] Conta Salicacee_Salice comune NUMERIC 0 0 20 NUMERIC 0 7 048161 [SIM] Conta Salicacee_Pioppo NUMERIC 0 0 20 NUMERIC 0 7 048162 [SIM] Conta Salicacee_Salicacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048163 [SIM] Conta Ciperacee_Ciperacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048164 [SIM] Conta Juglandacee_Juglandacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048165 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048166 [SIM] Conta Spore fungine_Alternaria NUMERIC 0 0 20 NUMERIC 0 7 048167 [SIM] Conta Spore fungine_Botrytis NUMERIC 0 0 20 NUMERIC 0 7 048168 [SIM] Conta Spore fungine_Stemphylium NUMERIC 0 0 20 NUMERIC 0 7 048169 [SIM] Conta Spore fungine_Cladosporium NUMERIC 0 0 20 NUMERIC 0 7 048170 [SIM] Conta Spore fungine_Epicoccum NUMERIC 0 0 20 NUMERIC 0 7 048171 [SIM] Conta Altri Pollini / Non Identificati_Altri pollini ident NUMERIC 0 0 20 NUMERIC 0 7 048172 [SIM] Conta Altri Pollini / Non Identificati_Pollini non identif NUMERIC 0 0 20 NUMERIC 0 7 048173 [SIM] Conta Altre Spore / Non identificati_Altre spore fungine NUMERIC 0 0 20 NUMERIC 0 7 048174 [SIM] Conta Altre Spore / Non identificati_Spore fungine non ide NUMERIC 0 0 20 NUMERIC 0 7 048175 [SIM] Conta Graminacee_Graminacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048176 [SIM] Conta Plantaginacee_Plantaginacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048177 [SIM] Conta Urticacee_Urticacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048178 [SIM] Conta Poligonacee_Poligonacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048179 [SIM] Conta Euphorbiacee_Euforbiacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048180 [SIM] Conta Mirtacee_Mirtacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048181 [SIM] Conta Platanacee_Platanacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048182 [SIM] Conta Aceraceae_Aceracee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048183 [SIM] Conta Pinacee_Pinacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048184 [SIM] Conta Ciperacee_Ciperacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048185 [SIM] Conta Juglandacee_Juglandacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048186 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048187 [SIM] Conta Oleacee_Ligustro NUMERIC 0 0 20 NUMERIC 0 7 dballe-7.7/tables/B000000002001400.txt0000644000175000017500000016761012652630120013266 00000000000000 001001 WMO BLOCK NUMBER NUMERIC 0 0 7 001002 WMO STATION NUMBER NUMERIC 0 0 10 001006 AIRCRAFT FLIGHT NUMBER CCITTIA5 0 0 64 001007 SATELLITE IDENTIFIER CODE TABLE 1007 0 0 10 001008 AIRCRAFT REGISTRATION NUMBER OR OTHER IDENTIFICATION CCITTIA5 0 0 64 001011 SHIP OR MOBILE LAND STATION IDENTIFIER CCITTIA5 0 0 72 001012 DIRECTION OF MOTION OF MOVING OBSERVING PLATFORM** DEGREE TRUE 0 0 9 001013 SPEED OF MOTION OF MOVING OBSERVING PLATFORM* M/S 0 0 10 001019 LONG STATION OR SITE NAME CCITTIA5 0 0 256 001023 OBSERVATION SEQUENCE NUMBER NUMERIC 0 0 9 001033 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE CODE TABLE 001033 0 0 8 001034 IDENTIFICATION OF ORIGINATING/GENERATING SUB-CENTRE CODE TABLE 001034 0 0 8 001063 ICAO LOCATION INDICATOR CCITTIA5 0 0 64 001192 [SIM] MeteoDB station ID NUMERIC 0 0 24 001193 [SIM] Report code NUMERIC 0 0 16 001194 [SIM] Report mnemonic CCITTIA5 0 0 128 001212 AIR QUALITY OBSERVING STATION LOCAL CODE CCITTIA5 0 0 56 001213 AIRBASE AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 56 001214 GEMS AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 48 001215 AIR QUALITY OBSERVING STATION DOMINANT EMISSION SOURCE CODE TABLE 001215 0 0 3 001216 AIR QUALITY OBSERVING STATION AREA TYPE CODE TABLE 001216 0 0 3 001217 AIR QUALITY OBSERVING STATION TERRAIN TYPE CODE TABLE 001217 0 0 4 002001 TYPE OF STATION CODE TABLE 2001 0 0 2 002002 TYPE OF INSTRUMENTATION FOR WIND MEASUREMENT FLAG TABLE 2002 0 0 4 002003 TYPE OF MEASURING EQUIPMENT USED CODE TABLE 2003 0 0 4 002004 TYPE OF INSTRUMENTATION FOR EVAPORATION MEASUREMENT OR TYPE OF C CODE TABLE 2004 0 0 4 002005 PRECISION OF TEMPERATURE OBSERVATION K 2 0 7 002011 RADIOSONDE TYPE CODE TABLE 2011 0 0 8 002012 RADIOSONDE COMPUTATIONAL METHOD CODE TABLE 2012 0 0 4 002013 SOLAR AND INFRARED RADIATION CORRECTION CODE TABLE 2013 0 0 4 002014 TRACKING TECHNIQUE/STATUS OF SYSTEM USED CODE TABLE 2014 0 0 7 002038 METHOD OF WATER TEMPERATURE AND/OR SALINITY MEASUREMENT CODE TABLE 2038 0 0 4 002039 METHOD OF WET-BULB TEMPERATURE MEASUREMENT CODE TABLE 2039 0 0 3 002048 SATELLITE SENSOR INDICATOR CODE TABLE 2048 0 0 4 002061 AIRCRAFT NAVIGATIONAL SYSTEM CODE TABLE 2061 0 0 3 002062 TYPE OF AIRCRAFT DATA RELAY SYSTEM CODE TABLE 2062 0 0 4 002063 AIRCRAFT ROLL ANGLE DEGREE 2 -18000 16 002064 AIRCRAFT ROLL ANGLE QUALITY CODE TABLE 2064 0 0 2 002070 ORIGINAL SPECIFICATION OF LATITUDE/LONGITUDE CODE TABLE 2070 0 0 4 002121 MEAN FREQUENCY Hz -8 0 7 002125 PULSE REPETITION FREQUENCY Hz -1 0 8 004001 YEAR YEAR 0 0 12 004002 MONTH MONTH 0 0 4 004003 DAY DAY 0 0 6 004004 HOUR HOUR 0 0 5 004005 MINUTE MINUTE 0 0 6 004006 SECOND SECOND 0 0 6 004086 LONG TIME PERIOD OR DISPLACEMENT SECOND 0 -8192 15 004192 [SIM] Time range type NUMERIC 0 0 10 004193 [SIM] Time range P1 NUMERIC 0 -536870912 31 004194 [SIM] Time range P2 NUMERIC 0 -536870912 31 004195 [SIM] Temperature event - time of occurrence MINUTE 0 0 11 004196 [SIM] Relative humidity event - time of occurrence MINUTE 0 0 11 004197 [SIM] Wind velocity event - time of occurrence MINUTE 0 0 11 004198 [SIM] Pressure event - time of occurrence MINUTE 0 0 11 005001 LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 005015 LATITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -9000000 25 005021 BEARING OR AZIMUTH DEGREE TRUE 2 0 16 005022 SOLAR AZIMUTH DEGREE TRUE 2 0 16 005040 ORBIT NUMBER NUMERIC 0 0 24 005041 SCAN LINE NUMBER NUMERIC 0 0 8 005043 FIELD OF VIEW NUMBER NUMERIC 0 0 8 006001 LONGITUDE (HIGH ACCURACY) DEGREE 5 -18000000 26 006015 LONGITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -18000000 26 007002 HEIGHT OR ALTITUDE M -1 -40 16 007004 PRESSURE PA -1 0 14 007007 HEIGHT M 0 -1000 17 007010 FLIGHT LEVEL M 0 -1024 16 007024 SATELLITE ZENITH ANGLE DEGREE 2 -9000 15 007025 SOLAR ZENITH ANGLE DEGREE 2 -9000 15 007030 HEIGHT OF STATION GROUND ABOVE MEAN SEA LEVEL (SEE NOTE 3) M 1 -4000 17 007031 HEIGHT OF BAROMETER ABOVE MEAN SEA LEVEL (SEE NOTE 4) M 1 - 4000 17 007032 HEIGHT OF SENSOR ABOVE LOCAL GROUND (OR DECK OF MARINE PLATFORM) M 2 0 16 007192 [SIM] First level type NUMERIC 0 0 10 007193 [SIM] Level L1 NUMERIC 0 -536870912 31 007194 [SIM] Level L2 NUMERIC 0 -536870912 31 007195 [SIM] Second level type NUMERIC 0 0 31 008002 VERTICAL SIGNIFICANCE (SURFACE OBSERVATIONS) CODE TABLE 8002 0 0 6 008004 PHASE OF AIRCRAFT FLIGHT CODE TABLE 8004 0 0 3 008009 DETAILED PHASE OF FLIGHT CODE TABLE 8009 0 0 4 008021 TIME SIGNIFICANCE CODE TABLE 8021 0 0 5 008042 EXTENDED VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8042 0 0 18 008044 (VAL) CAS REGISTRY NUMBER CCITTIA5 0 0 88 008192 [SIM] Number of wind velocity mean values present NUMERIC 0 0 5 008193 [SIM] Number of wind velocity minimum values present NUMERIC 0 0 5 008194 [SIM] Number of wind velocity maximum values present NUMERIC 0 0 5 008195 [SIM] Number of wind prevalent direction values present NUMERIC 0 0 5 008196 [SIM] Number of mean temperature values present NUMERIC 0 0 5 008197 [SIM] Number of minimum temperature values present NUMERIC 0 0 5 008198 [SIM] Number of maximum temperature values present NUMERIC 0 0 5 008199 [SIM] Number of mean relative humidity values present NUMERIC 0 0 5 008200 [SIM] Number of minimum relative humidity values present NUMERIC 0 0 5 008201 [SIM] Number of maximum relative humidity values present NUMERIC 0 0 5 008202 [SIM] Number of mean pressure values present NUMERIC 0 0 5 008203 [SIM] Number of minimum pressure values present NUMERIC 0 0 5 008204 [SIM] Number of maximum pressure values present NUMERIC 0 0 5 008205 [SIM] Number of precipitation values present NUMERIC 0 0 5 008206 [SIM] Number of leaf wetness values present NUMERIC 0 0 5 008207 [SIM] Number of scalar wind velocity mean values present NUMERIC 0 0 5 008208 [SIM] Number of cloud cover mean values present NUMERIC 0 0 5 008209 [SIM] Number of cloud cover maximum values present NUMERIC 0 0 5 008210 [SIM] Number of cloud cover minimum values present NUMERIC 0 0 5 010004 PRESSURE PA -1 0 14 010007 HEIGHT M 0 -1000 17 010008 GEOPOTENTIAL M**2/S**2 0 -10000 20 010009 GEOPOTENTIAL HEIGHT GPM 0 -1000 17 010051 PRESSURE REDUCED TO MEAN SEA LEVEL PA -1 0 14 010052 ALTIMETER SETTING (QNH) PA -1 0 14 010060 PRESSURE CHANGE PA -1 -1024 11 010063 CHARACTERISTIC OF PRESSURE TENDENCY CODE TABLE 10063 0 0 4 010197 ANEMOMETER HEIGHT M 0 0 9 011001 WIND DIRECTION DEGREE TRUE 0 0 9 011002 WIND SPEED M/S 1 0 12 011003 U-COMPONENT M/S 1 -4096 13 011004 V-COMPONENT M/S 1 -4096 13 011005 W-COMPONENT PA/S 1 -512 10 011006 W-COMPONENT M/S 2 -4096 13 011016 EXTREME COUNTERCLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 011017 EXTREME CLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 011031 DEGREE OF TURBULENCE CODE TABLE 11031 0 0 4 011036 MAXIMUM DERIVED EQUIVALENT VERTICAL GUST SPEED M/S 1 0 10 011037 TURBULENCE INDEX CODE TABLE 11037 0 0 6 011039 EXTENDED TIME OF OCCURRENCE OF PEAK EDDY DISSIPATION RATE CODE TABLE 11039 0 0 6 011041 MAXIMUM WIND GUST SPEED M/S 1 0 12 011043 MAXIMUM WIND GUST DIRECTION DEGREE TRUE 0 0 9 011050 STANDARD DEVIATION OF HORIZONTAL WIND SPEED M/S 1 0 12 011061 ABSOLUTE WIND SHEAR IN 1 KM LAYER BELOW M/S 1 0 12 011062 ABSOLUTE WIND SHEAR IN 1 KM LAYER ABOVE M/S 1 0 12 011075 MEAN TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 011076 PEAK TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 011077 REPORTING INTERVAL OR AVERAGING TIME FOR EDDY DISSIPATION RATE S 0 0 12 011192 [SIM] W-component terrain following M/S 2 -4096 13 011193 [SIM] Stability class NUMERIC 0 0 4 011194 [SIM] Friction velocity (calmet) M/S 3 0 14 011195 [SIM] Mixing height (calmet) M 0 0 12 011196 [SIM] Obukov lenght (calmet) M 1 -100000 15 011197 [SIM] Convective velocitiy scale (calmet) M/S 3 0 14 011198 [SIM] SQRT(2*TKE) M/S 4 0 20 011199 [SIM] Surface Roughness M 3 0 14 011200 [SIM] U-component of momentum flux N/M**2 4 -524288 20 011201 [SIM] V-component of momentum flux N/M**2 4 -524288 20 011202 [SIM] Friction velocity (diagmet) M/S 3 0 14 011203 [SIM] Mixing height (diagmet) M 0 0 12 011204 [SIM] Obukov lenght (diagmet) M 1 -100000 15 011205 [SIM] Convective velocitiy scale (diagmet) M/S 3 0 14 011206 [SIM] Friction velocity (COSMO) M/S 3 0 14 011207 [SIM] Obukov lenght (COSMO) M 1 -100000 15 011208 [SIM] Distance covered by the hourly mean wind M 0 0 23 012001 TEMPERATURE/AIR TEMPERATURE K 1 0 12 012003 DEW-POINT TEMPERATURE K 1 0 12 012030 SOIL TEMPERATURE K 1 0 12 012049 Temperature change over specified period K 0 -30 6 012061 SKIN TEMPERATURE K 1 0 12 012063 BRIGHTNESS TEMPERATURE K 1 0 12 012101 TEMPERATURE/DRY-BULB TEMPERATURE K 2 0 16 012102 WET-BULB TEMPERATURE K 2 0 16 012103 DEW-POINT TEMPERATURE K 2 0 16 012121 GROUND MINIMUM TEMPERATURE K 2 0 16 012131 SNOW TEMPERATURE K 2 0 16 012192 POTENTIAL TEMPERATURE K 2 0 16 012193 PSEUDO-EQUIVALENT POTENTIAL TEMPERATURE K 2 0 16 012194 [SIM] Air density KG/M**3 6 0 20 013001 SPECIFIC HUMIDITY KG/KG 5 0 14 013002 MIXING RATIO KG/KG 5 0 14 013003 RELATIVE HUMIDITY % 0 0 7 013011 TOTAL PRECIPITATION / TOTAL WATER EQUIVALENT KG/M**2 1 -1 14 013012 DEPTH OF FRESH SNOW M 2 -2 12 013013 TOTAL SNOW DEPTH M 3 -20 20 013031 EVAPOTRANSPIRATION KG/M**2 1 0 7 013033 EVAPORATION/EVAPOTRANSPIRATION KG/M**2 1 0 10 013081 WATER CONDUCTIVITY S/M 3 0 14 013082 WATER TEMPERATURE K 1 0 12 013192 [SIM] Cloud liquid water content KG/KG 8 0 27 013193 [SIM] Cloud ice content KG/KG 8 0 27 013194 [SIM] Water table depth M 3 0 18 013195 [SIM] Precipitating liquid water KG/KG 8 0 27 013196 [SIM] Precipitating ice KG/KG 8 0 27 013197 [SIM] Total precipitating water+ice KG/KG 8 0 27 013198 [SIM] Total liquid water (cloud+precipitating) KG/KG 8 0 27 013199 [SIM] Total ice (cloud+precipitating) KG/KG 8 0 27 013200 [SIM] Grid-scale liquid precipitation KG/M**2 1 -1 14 013201 [SIM] Grid-scale snowfall KG/M**2 1 -1 14 013202 [SIM] Convective liquid precipitation KG/M**2 1 -1 14 013203 [SIM] Convective snowfall KG/M**2 1 -1 14 013204 [SIM] Total convective precipitation (liquid + snow) KG/M**2 1 -1 14 013205 [SIM] Snowfall (grid-scale + convective) KG/M**2 1 -1 14 013206 [SIM] Soil water content KG/M**2 1 0 14 013210 [SIM] Penetration of the probe in the snow M 2 0 9 013212 [SIM] Leaf wetness duration S -1 0 24 013215 [SIM] River level M 2 -100000 18 013216 [SIM] Hourly precipitation KG/M**2 1 -1 14 013217 [SIM] 5 minutes precipitation KG/M**2 1 -1 14 013218 [SIM] 10 minutes precipitation KG/M**2 1 -1 14 013219 [SIM] 15 minutes precipitation KG/M**2 1 -1 14 013220 [SIM] 20 minutes precipitation KG/M**2 1 -1 14 013221 [SIM] 30 minutes precipitation KG/M**2 1 -1 14 013222 [SIM] 180 minutes precipitation KG/M**2 1 -1 14 013223 [SIM] 360 minutes precipitation KG/M**2 1 -1 14 013224 [SIM] 720 minutes precipitation KG/M**2 1 -1 14 013225 [SIM] 1440 minutes precipitation KG/M**2 1 -1 14 013226 [SIM] River discharge M**3/S 2 0 21 013227 [SIM] Soil volumetric water content % 1 0 10 013228 [SIM] Piezometric level M 3 0 18 013229 [SIM] Density of snow KG/M**3 1 0 14 013230 [SIM] Convective Available Potential Energy (CAPE) J/KG 1 0 17 014002 Long-wave radiation, integrated over period specified J M-2 -3 -65536 17 014004 Short-wave radiation, integrated over period specified J M-2 -3 -65536 17 014016 NET RADIATION J/M**2 -4 -16384 15 014017 INSTANTANEOUS LONG-WAVE RADIATION (incoming) W/M**2 0 -2048 12 014018 INSTANTANEOUS SHORT-WAVE RADIATION (incoming) W/M**2 0 -2048 12 014019 SURFACE ALBEDO % 0 0 7 014021 GLOBAL SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 014028 Global solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 014029 Diffuse solar radiation (high accuracy), integrated over period J M-2 -2 0 20 014030 Direct solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 014031 TOTAL SUNSHINE MINUTE 0 0 11 014192 [SIM] Instantenous sensible heat flux W/m**2 0 -1024 11 014193 [SIM] Instantenous latent heat flux W/m**2 0 -1024 11 014194 [SIM] Instantenous direct solar radiation W/M**2 0 -2048 12 014195 [SIM] Instantenous diffuse solar radiation W/M**2 0 -2048 12 014196 [SIM] INSTANTANEOUS NET LONG-WAVE RADIATION W/M**2 0 -2048 12 014197 [SIM] INSTANTANEOUS NET SHORT-WAVE RADIATION W/M**2 0 -2048 12 014198 [SIM] Visible radiation (downward) W/M**2 3 -50000 21 014199 [SIM] Visible radiation (upward) W/M**2 3 -50000 21 014200 [SIM] Infrared radiation (downward) W/M**2 3 0 20 014201 [SIM] Infrared radiation (upward) W/M**2 3 0 20 015192 [SIM] NO Concentration KG/M**3 10 0 20 015193 [SIM] NO2 Concentration KG/M**3 10 0 20 015194 [SIM] O3 Concentration KG/M**3 10 0 20 015195 [SIM] PM10 Concentration KG/M**3 10 0 20 015196 [SIM] CO Concentration KG/M**3 10 0 20 015197 [SIM] SO2 Concentration KG/M**3 10 0 20 015198 [SIM] PM2.5 Concentration KG/M**3 10 0 20 015199 [SIM] NOY Concentration KG/M**3 10 0 20 015200 [SIM] HCNM Concentration KG/M**3 10 0 20 015201 [SIM] ALDE Concentration KG/M**3 10 0 20 015202 [SIM] PM5 Concentration (tot. aerosol < 5 ug) KG/M**3 10 0 20 015203 [SIM] PM1 Concentration (tot. aerosol < 1.25 ug) KG/M**3 10 0 20 015204 [SIM] PM06 Concentration (tot. aerosol < 0.6 ug) KG/M**3 10 0 20 015205 [SIM] PM03 Concentration (tot. aerosol < 0.3 ug) KG/M**3 10 0 20 015206 [SIM] PM015 Concentration (tot. aerosol < 0.15 ug) KG/M**3 10 0 20 015207 [SIM] PM008 Concentration (tot. aerosol < 0.08 ug) KG/M**3 10 0 20 015208 [SIM] Concentration of primary particulate matter in PM10 KG/M**3 10 0 20 015209 [SIM] Concentration of sulfate in PM10 KG/M**3 10 0 20 015210 [SIM] Concentration of nitrate in PM10 KG/M**3 10 0 20 015211 [SIM] Concentration of ammonium in PM10 KG/M**3 10 0 20 015212 [SIM] Concentration of black carbon in PM10 KG/M**3 10 0 20 015213 [SIM] Concentration of organic carbon in PM10 KG/M**3 10 0 20 015214 [SIM] Concentration of dust in PM10 KG/M**3 10 0 20 015215 [SIM] Concentration of anthrop. A1D in PM10 KG/M**3 10 0 20 015216 [SIM] Concentration of anthrop. BmP in PM10 KG/M**3 10 0 20 015217 [SIM] Concentration of biogenic A1D in PM10 KG/M**3 10 0 20 015218 [SIM] Concentration of biogenic BmP in PM10 KG/M**3 10 0 20 015219 [SIM] Concentration of water in PM10 KG/M**3 10 0 20 015220 [SIM] Concentration of sea salt in PM10 KG/M**3 10 0 20 015221 [SIM] Concentration of secondary organic aerosol in PM10 KG/M**3 10 0 20 015222 [SIM] Total concentration of primary aerosol in PM10 KG/M**3 10 0 20 015223 [SIM] Total concentration of secondary aerosol in PM10 KG/M**3 10 0 20 015224 [SIM] Uncertainity in O3 estimate (Pesco) KG/M**3 10 0 20 015225 [SIM] Uncertainity in PM10 estimate (Pesco) KG/M**3 10 0 20 015226 [SIM] Uncertainity in NO2 estimate (Pesco) KG/M**3 10 0 20 015227 [SIM] Uncertainity in PM2.5 estimate (Pesco) KG/M**3 10 0 20 015228 [SIM] NH3 Concentration KG/M**3 10 0 20 015229 [SIM] Concentration of primary part. matter in aerosol KG/M**3 10 0 20 015230 [SIM] Concentration of sulfate in aerosol KG/M**3 10 0 20 015231 [SIM] Concentration of nitrate in aerosol KG/M**3 10 0 20 015232 [SIM] Concentration of ammonium in aerosol KG/M**3 10 0 20 015233 [SIM] Concentration of anthrop. sec. org. in aerosol KG/M**3 10 0 20 015234 [SIM] Concentration of biogenic sec. org. in aerosol KG/M**3 10 0 20 015235 [SIM] Concentration of ISOPA1 in PM10 KG/M**3 10 0 20 015236 [SIM] C6H6 Concentration KG/M**3 10 0 20 015237 [SIM] Concentration of anthropogenic aerosol in PM10 KG/M**3 10 0 20 015238 [SIM] Concentration of biogenic aerosol in PM10 KG/M**3 10 0 20 015239 [SIM] Concentration of anthropogenic aerosol in PM2.5 KG/M**3 10 0 20 015240 [SIM] Concentration of biogenic aerosol in PM2.5 KG/M**3 10 0 20 015241 [SIM] Aerosol Optical Thickness NUMERIC 4 0 15 020001 HORIZONTAL VISIBILITY M -1 0 13 020003 PRESENT WEATHER (SEE NOTE 1) CODE TABLE 20003 0 0 9 020004 PAST WEATHER (1) (SEE NOTE 2) CODE TABLE 20004 0 0 5 020005 PAST WEATHER (2) (SEE NOTE 2) CODE TABLE 20005 0 0 5 020009 GENERAL WEATHER INDICATOR (TAF/METAR) CODE TABLE 20009 0 0 4 020010 CLOUD COVER (TOTAL) % 0 0 7 020011 CLOUD AMOUNT CODE TABLE 20011 0 0 4 020012 CLOUD TYPE CODE TABLE 20012 0 0 6 020013 HEIGHT OF BASE OF CLOUD M 0 -400 17 020017 CLOUD TOP DESCRIPTION CODE TABLE 20017 0 0 4 020019 SIGNIFICANT PRESENT OR FORECAST WEATHER CCITTIA5 0 0 72 020021 TYPE OF PRECIPITATION FLAG TABLE 20021 0 0 30 020031 ICE DEPOSIT (THICKNESS) M 2 0 7 020032 RATE OF ICE ACCRETION CODE TABLE 20032 0 0 3 020033 CAUSE OF ICE ACCRETION FLAG TABLE 20033 0 0 4 020034 SEA ICE CONCENTRATION CODE TABLE 20034 0 0 5 020035 AMOUNT AND TYPE OF ICE CODE TABLE 20035 0 0 4 020036 ICE SITUATION CODE TABLE 20036 0 0 5 020037 ICE DEVELOPMENT CODE TABLE 20037 0 0 5 020038 BEARING OF ICE EDGE (SEE NOTE 3) DEGREE TRUE 0 0 12 020042 AIRFRAME ICING PRESENT CODE TABLE 20042 0 0 2 020043 PEAK LIQUID WATER CONTENT KG/M**3 4 0 7 020044 AVERAGE LIQUID WATER CONTENT KG/M**3 4 0 7 020045 SUPERCOOLED LARGE DROPLET (SLD) CONDITIONS CODE TABLE 20045 0 0 2 020062 STATE OF THE GROUND (WITH OR WITHOUT SNOW) CODE TABLE 20062 0 0 5 020192 [SIM] Presence of rain > 1mm BOOLEAN 0 0 1 020193 [SIM] Cloud type (METAR) CCITTIA5 0 0 16 020194 [SIM] Presence of shower BOOLEAN 0 0 1 020195 [SIM] Presence of hail BOOLEAN 0 0 1 020196 [SIM] Presence of thunderstorm BOOLEAN 0 0 1 020197 [SIM] Presence of snow BOOLEAN 0 0 1 020198 [SIM] Presence of frost BOOLEAN 0 0 1 020199 [SIM] Presence of dew BOOLEAN 0 0 1 020200 [SIM] Presence of fog BOOLEAN 0 0 1 020201 [SIM] Presence of water-spout BOOLEAN 0 0 1 020202 [SIM] State of the ground with snow CODE TABLE 0 0 5 022001 DIRECTION OF WAVES DEGREE TRUE 0 0 9 022002 DIRECTION OF WIND WAVES DEGREE TRUE 0 0 9 022003 DIRECTION OF SWELL WAVES DEGREE TRUE 0 0 9 022004 DIRECTION OF CURRENT DEGREE TRUE 0 0 9 022011 PERIOD OF WAVES S 0 0 6 022012 PERIOD OF WIND WAVES S 0 0 6 022013 PERIOD OF SWELL WAVES S 0 0 6 022021 HEIGHT OF WAVES M 1 0 10 022022 HEIGHT OF WIND WAVES M 1 0 10 022023 HEIGHT OF SWELL WAVES M 1 0 10 022031 SPEED OF CURRENT M/S 2 0 13 022032 SPEED OF SEA SURFACE CURRENT M/S 2 0 13 022037 Tidal elevation with respect to national land datum M 3 -10000 15 022038 Tidal elevation with respect to local chart datum M 3 -10000 15 022042 SEA/WATER TEMPERATURE K 1 0 12 022043 SEA/WATER TEMPERATURE K 2 0 15 022049 SEA-SURFACE TEMPERATURE K 2 0 15 022070 SIGNIFICANT WAVE HEIGHT M 2 0 13 022071 SPECTRAL PEAK WAVE PERIOD S 1 0 9 022074 AVERAGE WAVE PERIOD S 1 0 9 022192 [SIM] Current X component M/S 2 0 13 022193 [SIM] Current Y component M/S 2 0 13 023192 [SIM] Dry deposition of H2SO4 MOL/M**2 5 0 20 023193 [SIM] Wet deposition of H2SO4 MOL/M**2 5 0 20 023194 [SIM] Dry deposition of NH4 MOL/M**2 5 0 20 023195 [SIM] Wet deposition of NH4 MOL/M**2 5 0 20 023196 [SIM] Dry deposition of HNO3 MOL/M**2 5 0 20 023197 [SIM] Wet deposition of HNO3 MOL/M**2 5 0 20 023198 [SIM] Solid transport by river KG/S 2 0 24 025076 LOG-10 OF (TEMP-RAD CENTRAL WAVENUMBER) FOR ATOVS LOGM-1 8 0 30 029192 [SIM] Land fraction % 1 0 10 031000 SHORT DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 1 031001 DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 8 031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 16 031011 DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 8 031012 EXTENDED DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 16 031021 ASSOCIATED FIELD SIGNIFICANCE CODE TABLE 31021 0 0 6 031031 DATA PRESENT INDICATOR FLAG TABLE 31031 0 0 1 033002 QUALITY INFORMATION CODE TABLE 33002 0 0 2 033003 QUALITY INFORMATION CODE TABLE 33003 0 0 3 033005 QUALITY INFORMATION (AWS DATA) FLAG TABLE 33005 0 0 30 033006 INTERNAL MEASUREMENT STATUS INFORMATION (AWS) CODE TABLE 33006 0 0 3 033007 PER CENT CONFIDENCE % 0 0 7 033015 DATA QUALITY CHECK INDICATOR CODE TABLE 33015 0 0 6 033020 QUALITY CONTROL INDICATION OF FOLLOWING VALUE CODE TABLE 33020 0 0 3 033021 QUALITY OF FOLLOWING VALUE CODE TABLE 33021 0 0 2 033022 QUALITY OF BUOY SATELLITE TRANSMISSION CODE TABLE 33022 0 0 2 033023 QUALITY OF BUOY LOCATION CODE TABLE 33023 0 0 2 033024 STATION ELEVATION QUALITY MARK (FOR MOBILE STATIONS) CODE TABLE 33024 0 0 4 033025 ACARS INTERPOLATED VALUES CODE TABLE 33025 0 0 3 033026 MOISTURE QUALITY CODE TABLE 33026 0 0 6 033027 LOCATION QUALITY CLASS (RANGE OF RADIUS OF 66 % CONFIDENCE) CODE TABLE 33027 0 0 3 033030 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 33030 0 0 24 033031 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 33031 0 0 24 033032 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 33032 0 0 24 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS FLAG TABLE 33033 0 0 24 033035 MANUAL/AUTOMATIC QUALITY CONTROL CODE TABLE 33035 0 0 4 033036 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 033037 WIND CORRELATION ERROR FLAG TABLE 33037 0 0 20 033038 QUALITY FLAGS FOR GROUND-BASED GNSS DATA FLAG TABLE 33038 0 0 10 033040 CONFIDENCE INTERVAL % 0 0 7 033041 ATTRIBUTE OF FOLLOWING VALUE CODE TABLE 33041 0 0 2 033050 GLOBAL GTSPP QUALITY FLAG CODE TABLE 33050 0 0 4 033192 [SIM] Climatological and consistency check % 0 0 7 033193 [SIM] Time consistency % 0 0 7 033194 [SIM] Space consistency % 0 0 7 033195 [SIM] MeteoDB variable ID NUMERIC 0 0 24 033196 [SIM] Data has been invalidated CODE TABLE 33196 0 0 2 033197 [SIM] Manual replacement in substitution CODE TABLE 33197 0 0 2 033198 [SIM] Observation increment NUMERIC 4 -1073741823 31 033201 [SIM] Kalman coefficient, state vector (s.v.) x1 NUMERIC 4 -1073741823 31 033202 [SIM] Kalman coefficient, state vector (s.v.) x2 NUMERIC 4 -1073741823 31 033203 [SIM] Kalman coefficient, s.v. error covariance matrix(1,1) NUMERIC 4 -1073741823 31 033204 [SIM] Kalman coefficient, s.v. error covariance matrix(1,2) NUMERIC 4 -1073741823 31 033205 [SIM] Kalman coefficient, s.v. error covariance matrix(2,1) NUMERIC 4 -1073741823 31 033206 [SIM] Kalman coefficient, s.v. error covariance matrix(2,2) NUMERIC 4 -1073741823 31 033207 [SIM] Kalman observation sequential counter NUMERIC 0 -127 8 033208 [SIM] Kalman osservation missing counter NUMERIC 0 -127 8 033209 [SIM] Normalized Density Index % 0 0 7 048001 [SIM] Graminacee_Graminacee indistinte POLLEN/M**3 1 0 24 048002 [SIM] Betulacee_Ontano nero POLLEN/M**3 1 0 24 048003 [SIM] Betulacee_Betulla POLLEN/M**3 1 0 24 048004 [SIM] Betulacee_Betulacee indistinte POLLEN/M**3 1 0 24 048005 [SIM] Composite_Ambrosia POLLEN/M**3 1 0 24 048006 [SIM] Composite_Artemisia POLLEN/M**3 1 0 24 048007 [SIM] Composite_Composite indistinte POLLEN/M**3 1 0 24 048008 [SIM] Corilacee_Nocciolo POLLEN/M**3 1 0 24 048009 [SIM] Corilacee_Carpino bianco -Carpino nero POLLEN/M**3 1 0 24 048010 [SIM] Corilacee_Corilacee indistinte POLLEN/M**3 1 0 24 048011 [SIM] Fagacee_Castagno POLLEN/M**3 1 0 24 048012 [SIM] Fagacee_Faggio POLLEN/M**3 1 0 24 048013 [SIM] Fagacee_Quercia POLLEN/M**3 1 0 24 048014 [SIM] Fagacee_Fagacee indistinte POLLEN/M**3 1 0 24 048015 [SIM] Oleacee_Olivo POLLEN/M**3 1 0 24 048016 [SIM] Oleacee_Frassino POLLEN/M**3 1 0 24 048017 [SIM] Oleacee_Oleacee indistinte POLLEN/M**3 1 0 24 048018 [SIM] Plantaginacee_Plantaginacee indistinte POLLEN/M**3 1 0 24 048019 [SIM] Urticacee_Urticacee indistinte POLLEN/M**3 1 0 24 048020 [SIM] Cupressacee - Taxacee indistinte_Cipresso comune POLLEN/M**3 1 0 24 048021 [SIM] Cupressacee - Taxacee indistinte_Cupressacee - Taxacee ind POLLEN/M**3 1 0 24 048022 [SIM] Chenopodiacee - Amarantacee Indistinte_Amaranto POLLEN/M**3 1 0 24 048023 [SIM] Chenopodiacee - Amarantacee Indistinte_Chenopodiacee - Ama POLLEN/M**3 1 0 24 048024 [SIM] Poligonacee_Poligonacee indistinte POLLEN/M**3 1 0 24 048025 [SIM] Euphorbiacee_Euforbiacee indistinte POLLEN/M**3 1 0 24 048026 [SIM] Mirtacee_Mirtacee indistinte POLLEN/M**3 1 0 24 048027 [SIM] Ulmacee_Bagolaro comune POLLEN/M**3 1 0 24 048028 [SIM] Ulmacee_Olmo campestre POLLEN/M**3 1 0 24 048029 [SIM] Ulmacee_Ulmacee indistinte POLLEN/M**3 1 0 24 048030 [SIM] Platanacee_Platanacee indistinte POLLEN/M**3 1 0 24 048031 [SIM] Aceraceae_Aceracee indistinte POLLEN/M**3 1 0 24 048032 [SIM] Pinacee_Pinacee indistinte POLLEN/M**3 1 0 24 048033 [SIM] Salicacee_Salice comune POLLEN/M**3 1 0 24 048034 [SIM] Salicacee_Pioppo POLLEN/M**3 1 0 24 048035 [SIM] Salicacee_Salicacee indistinte POLLEN/M**3 1 0 24 048036 [SIM] Ciperacee_Ciperacee indistinte POLLEN/M**3 1 0 24 048037 [SIM] Juglandacee_Juglandacee indistinte POLLEN/M**3 1 0 24 048038 [SIM] Ippocastanacee_Ippocastanacee indistinte POLLEN/M**3 1 0 24 048039 [SIM] Spore fungine_Alternaria POLLEN/M**3 1 0 24 048040 [SIM] Spore fungine_Botrytis POLLEN/M**3 1 0 24 048041 [SIM] Spore fungine_Stemphylium POLLEN/M**3 1 0 24 048042 [SIM] Spore fungine_Cladosporium POLLEN/M**3 1 0 24 048043 [SIM] Spore fungine_Epicoccum POLLEN/M**3 1 0 24 048044 [SIM] Altri Pollini / Non Identificati_Altri pollini identificat POLLEN/M**3 1 0 24 048045 [SIM] Altri Pollini / Non Identificati_Pollini non identificati POLLEN/M**3 1 0 24 048046 [SIM] Altre Spore / Non identificati_Altre spore fungine POLLEN/M**3 1 0 24 048047 [SIM] Altre Spore / Non identificati_Spore fungine non identific POLLEN/M**3 1 0 24 048048 [SIM] Graminacee_Graminacee indistinte 1 POLLEN/M**3 1 0 24 048049 [SIM] Plantaginacee_Plantaginacee indistinte 1 POLLEN/M**3 1 0 24 048050 [SIM] Urticacee_Urticacee indistinte 1 POLLEN/M**3 1 0 24 048051 [SIM] Poligonacee_Poligonacee indistinte 1 POLLEN/M**3 1 0 24 048052 [SIM] Euphorbiacee_Euforbiacee indistinte 1 POLLEN/M**3 1 0 24 048053 [SIM] Mirtacee_Mirtacee indistinte 1 POLLEN/M**3 1 0 24 048054 [SIM] Platanacee_Platanacee indistinte 1 POLLEN/M**3 1 0 24 048055 [SIM] Aceraceae_Aceracee indistinte 1 POLLEN/M**3 1 0 24 048056 [SIM] Pinacee_Pinacee indistinte 1 POLLEN/M**3 1 0 24 048057 [SIM] Ciperacee_Ciperacee indistinte 1 POLLEN/M**3 1 0 24 048058 [SIM] Juglandacee_Juglandacee indistinte 1 POLLEN/M**3 1 0 24 048059 [SIM] Ippocastanacee_Ippocastanacee indistinte 1 POLLEN/M**3 1 0 24 048060 [SIM] Oleacee_Ligustro POLLEN/M**3 1 0 24 048128 [SIM] Conta Graminacee_Graminacee indistinte NUMERIC 0 0 20 048129 [SIM] Conta Betulacee_Ontano nero NUMERIC 0 0 20 048130 [SIM] Conta Betulacee_Betulla NUMERIC 0 0 20 048131 [SIM] Conta Betulacee_Betulacee indistinte NUMERIC 0 0 20 048132 [SIM] Conta Composite_Ambrosia NUMERIC 0 0 20 048133 [SIM] Conta Composite_Artemisia NUMERIC 0 0 20 048134 [SIM] Conta Composite_Composite indistinte NUMERIC 0 0 20 048135 [SIM] Conta Corilacee_Nocciolo NUMERIC 0 0 20 048136 [SIM] Conta Corilacee_Carpino bianco -Carpino nero NUMERIC 0 0 20 048137 [SIM] Conta Corilacee_Corilacee indistinte NUMERIC 0 0 20 048138 [SIM] Conta Fagacee_Castagno NUMERIC 0 0 20 048139 [SIM] Conta Fagacee_Faggio NUMERIC 0 0 20 048140 [SIM] Conta Fagacee_Quercia NUMERIC 0 0 20 048141 [SIM] Conta Fagacee_Fagacee indistinte NUMERIC 0 0 20 048142 [SIM] Conta Oleacee_Olivo NUMERIC 0 0 20 048143 [SIM] Conta Oleacee_Frassino NUMERIC 0 0 20 048144 [SIM] Conta Oleacee_Oleacee indistinte NUMERIC 0 0 20 048145 [SIM] Conta Plantaginacee_Plantaginacee indistinte NUMERIC 0 0 20 048146 [SIM] Conta Urticacee_Urticacee indistinte NUMERIC 0 0 20 048147 [SIM] Conta Cupressacee - Taxacee indistinte_Cipresso comune NUMERIC 0 0 20 048148 [SIM] Conta Cupressacee - Taxacee indistinte_Cupressacee - Taxac NUMERIC 0 0 20 048149 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Amaranto NUMERIC 0 0 20 048150 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Chenopodiacee NUMERIC 0 0 20 048151 [SIM] Conta Poligonacee_Poligonacee indistinte NUMERIC 0 0 20 048152 [SIM] Conta Euphorbiacee_Euforbiacee indistinte NUMERIC 0 0 20 048153 [SIM] Conta Mirtacee_Mirtacee indistinte NUMERIC 0 0 20 048154 [SIM] Conta Ulmacee_Bagolaro comune NUMERIC 0 0 20 048155 [SIM] Conta Ulmacee_Olmo campestre NUMERIC 0 0 20 048156 [SIM] Conta Ulmacee_Ulmacee indistinte NUMERIC 0 0 20 048157 [SIM] Conta Platanacee_Platanacee indistinte NUMERIC 0 0 20 048158 [SIM] Conta Aceraceae_Aceracee indistinte NUMERIC 0 0 20 048159 [SIM] Conta Pinacee_Pinacee indistinte NUMERIC 0 0 20 048160 [SIM] Conta Salicacee_Salice comune NUMERIC 0 0 20 048161 [SIM] Conta Salicacee_Pioppo NUMERIC 0 0 20 048162 [SIM] Conta Salicacee_Salicacee indistinte NUMERIC 0 0 20 048163 [SIM] Conta Ciperacee_Ciperacee indistinte NUMERIC 0 0 20 048164 [SIM] Conta Juglandacee_Juglandacee indistinte NUMERIC 0 0 20 048165 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte NUMERIC 0 0 20 048166 [SIM] Conta Spore fungine_Alternaria NUMERIC 0 0 20 048167 [SIM] Conta Spore fungine_Botrytis NUMERIC 0 0 20 048168 [SIM] Conta Spore fungine_Stemphylium NUMERIC 0 0 20 048169 [SIM] Conta Spore fungine_Cladosporium NUMERIC 0 0 20 048170 [SIM] Conta Spore fungine_Epicoccum NUMERIC 0 0 20 048171 [SIM] Conta Altri Pollini / Non Identificati_Altri pollini ident NUMERIC 0 0 20 048172 [SIM] Conta Altri Pollini / Non Identificati_Pollini non identif NUMERIC 0 0 20 048173 [SIM] Conta Altre Spore / Non identificati_Altre spore fungine NUMERIC 0 0 20 048174 [SIM] Conta Altre Spore / Non identificati_Spore fungine non ide NUMERIC 0 0 20 048175 [SIM] Conta Graminacee_Graminacee indistinte 1 NUMERIC 0 0 20 048176 [SIM] Conta Plantaginacee_Plantaginacee indistinte 1 NUMERIC 0 0 20 048177 [SIM] Conta Urticacee_Urticacee indistinte 1 NUMERIC 0 0 20 048178 [SIM] Conta Poligonacee_Poligonacee indistinte 1 NUMERIC 0 0 20 048179 [SIM] Conta Euphorbiacee_Euforbiacee indistinte 1 NUMERIC 0 0 20 048180 [SIM] Conta Mirtacee_Mirtacee indistinte 1 NUMERIC 0 0 20 048181 [SIM] Conta Platanacee_Platanacee indistinte 1 NUMERIC 0 0 20 048182 [SIM] Conta Aceraceae_Aceracee indistinte 1 NUMERIC 0 0 20 048183 [SIM] Conta Pinacee_Pinacee indistinte 1 NUMERIC 0 0 20 048184 [SIM] Conta Ciperacee_Ciperacee indistinte 1 NUMERIC 0 0 20 048185 [SIM] Conta Juglandacee_Juglandacee indistinte 1 NUMERIC 0 0 20 048186 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte 1 NUMERIC 0 0 20 048187 [SIM] Conta Oleacee_Ligustro NUMERIC 0 0 20 dballe-7.7/tables/B000299.txt0000644000175000017500000023620212652630120012415 00000000000000 001001 WMO BLOCK NUMBER NUMERIC 0 0 7 NUMERIC 0 2 001002 WMO STATION NUMBER NUMERIC 0 0 10 NUMERIC 0 3 001006 AIRCRAFT FLIGHT NUMBER CCITTIA5 0 0 64 CHARACTER 0 8 001007 SATELLITE IDENTIFIER CODE TABLE 1007 0 0 10 CODE TABLE 1007 0 3 001008 AIRCRAFT REGISTRATION NUMBER OR OTHER IDENTIFICATION CCITTIA5 0 0 64 CHARACTER 0 8 001011 SHIP OR MOBILE LAND STATION IDENTIFIER CCITTIA5 0 0 72 CHARACTER 0 9 001012 DIRECTION OF MOTION OF MOVING OBSERVING PLATFORM** DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 001013 SPEED OF MOTION OF MOVING OBSERVING PLATFORM* M/S 0 0 10 M/S 0 3 001019 LONG STATION OR SITE NAME CCITTIA5 0 0 256 CHARACTER 0 32 001023 OBSERVATION SEQUENCE NUMBER NUMERIC 0 0 9 NUMERIC 0 3 001033 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE CODE TABLE 001033 0 0 8 CODE TABLE 001033 0 3 001034 IDENTIFICATION OF ORIGINATING/GENERATING SUB-CENTRE CODE TABLE 001034 0 0 8 CODE TABLE 001034 0 3 001063 ICAO LOCATION INDICATOR CCITTIA5 0 0 64 CHARACTER 0 8 001192 [SIM] MeteoDB station ID NUMERIC 0 0 24 NUMERIC 0 8 001193 [SIM] Report code NUMERIC 0 0 16 NUMERIC 0 5 001194 [SIM] Report mnemonic CCITTIA5 0 0 128 CHARACTER 0 16 001212 AIR QUALITY OBSERVING STATION LOCAL CODE CCITTIA5 0 0 56 CHARACTER 0 7 001213 AIRBASE AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 56 CHARACTER 0 7 001214 GEMS AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 48 CHARACTER 0 6 001215 AIR QUALITY OBSERVING STATION DOMINANT EMISSION SOURCE CODE TABLE 001215 0 0 3 CODE TABLE 001215 0 1 001216 AIR QUALITY OBSERVING STATION AREA TYPE CODE TABLE 001216 0 0 3 CODE TABLE 001216 0 1 001217 AIR QUALITY OBSERVING STATION TERRAIN TYPE CODE TABLE 001217 0 0 4 CODE TABLE 001217 0 2 002001 TYPE OF STATION CODE TABLE 2001 0 0 2 CODE TABLE 2001 0 1 002002 TYPE OF INSTRUMENTATION FOR WIND MEASUREMENT FLAG TABLE 2002 0 0 4 FLAG TABLE 2002 0 2 002003 TYPE OF MEASURING EQUIPMENT USED CODE TABLE 2003 0 0 4 CODE TABLE 2003 0 2 002004 TYPE OF INSTRUMENTATION FOR EVAPORATION MEASUREMENT OR TYPE OF C CODE TABLE 2004 0 0 4 CODE TABLE 2004 0 2 002005 PRECISION OF TEMPERATURE OBSERVATION K 2 0 7 K 2 3 002011 RADIOSONDE TYPE CODE TABLE 2011 0 0 8 CODE TABLE 2011 0 3 002012 RADIOSONDE COMPUTATIONAL METHOD CODE TABLE 2012 0 0 4 CODE TABLE 2012 0 2 002013 SOLAR AND INFRARED RADIATION CORRECTION CODE TABLE 2013 0 0 4 CODE TABLE 2013 0 2 002014 TRACKING TECHNIQUE/STATUS OF SYSTEM USED CODE TABLE 2014 0 0 7 CODE TABLE 2014 0 3 002038 METHOD OF WATER TEMPERATURE AND/OR SALINITY MEASUREMENT CODE TABLE 2038 0 0 4 CODE TABLE 2038 0 2 002039 METHOD OF WET-BULB TEMPERATURE MEASUREMENT CODE TABLE 2039 0 0 3 CODE TABLE 2039 0 1 002048 SATELLITE SENSOR INDICATOR CODE TABLE 2048 0 0 4 CODE TABLE 2048 0 2 002061 AIRCRAFT NAVIGATIONAL SYSTEM CODE TABLE 2061 0 0 3 CODE TABLE 2061 0 1 002062 TYPE OF AIRCRAFT DATA RELAY SYSTEM CODE TABLE 2062 0 0 4 CODE TABLE 2062 0 2 002063 AIRCRAFT ROLL ANGLE DEGREE 2 -18000 16 DEGREE 2 5 002064 AIRCRAFT ROLL ANGLE QUALITY CODE TABLE 2064 0 0 2 CODE TABLE 2064 0 1 002070 ORIGINAL SPECIFICATION OF LATITUDE/LONGITUDE CODE TABLE 2070 0 0 4 CODE TABLE 2070 0 2 002121 MEAN FREQUENCY Hz -8 0 7 Hz -8 3 002125 PULSE REPETITION FREQUENCY Hz -1 0 8 Hz -1 3 004001 YEAR YEAR 0 0 12 YEAR 0 4 004002 MONTH MONTH 0 0 4 MONTH 0 2 004003 DAY DAY 0 0 6 DAY 0 2 004004 HOUR HOUR 0 0 5 HOUR 0 2 004005 MINUTE MINUTE 0 0 6 MINUTE 0 2 004006 SECOND SECOND 0 0 6 SECOND 0 2 004086 LONG TIME PERIOD OR DISPLACEMENT SECOND 0 -8192 15 SECOND 0 5 004192 [SIM] Time range type NUMERIC 0 0 10 NUMERIC 0 4 004193 [SIM] Time range P1 NUMERIC 0 -536870912 31 NUMERIC 0 10 004194 [SIM] Time range P2 NUMERIC 0 -536870912 31 NUMERIC 0 10 004195 [SIM] Temperature event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 004196 [SIM] Relative humidity event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 004197 [SIM] Wind velocity event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 004198 [SIM] Pressure event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 005001 LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 005015 LATITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 005021 BEARING OR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005022 SOLAR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005040 ORBIT NUMBER NUMERIC 0 0 24 NUMERIC 0 8 005041 SCAN LINE NUMBER NUMERIC 0 0 8 NUMERIC 0 3 005043 FIELD OF VIEW NUMBER NUMERIC 0 0 8 NUMERIC 0 3 006001 LONGITUDE (HIGH ACCURACY) DEGREE 5 -18000000 26 DEGREE 5 8 006015 LONGITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -18000000 26 DEGREE 5 8 007002 HEIGHT OR ALTITUDE M -1 -40 16 M -1 5 007004 PRESSURE PA -1 0 14 PA -1 5 007007 HEIGHT M 0 -1000 17 M 0 6 007010 FLIGHT LEVEL M 0 -1024 16 FT -1 5 007024 SATELLITE ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007025 SOLAR ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007030 HEIGHT OF STATION GROUND ABOVE MEAN SEA LEVEL (SEE NOTE 3) M 1 -4000 17 M 1 5 007031 HEIGHT OF BAROMETER ABOVE MEAN SEA LEVEL (SEE NOTE 4) M 1 - 4000 17 M 1 5 007032 HEIGHT OF SENSOR ABOVE LOCAL GROUND (OR DECK OF MARINE PLATFORM) M 2 0 16 M 2 5 007192 [SIM] First level type NUMERIC 0 0 10 NUMERIC 0 4 007193 [SIM] Level L1 NUMERIC 0 -536870912 31 NUMERIC 0 10 007194 [SIM] Level L2 NUMERIC 0 -536870912 31 NUMERIC 0 10 007195 [SIM] Second level type NUMERIC 0 0 31 NUMERIC 0 4 008002 VERTICAL SIGNIFICANCE (SURFACE OBSERVATIONS) CODE TABLE 8002 0 0 6 CODE TABLE 8002 0 2 008004 PHASE OF AIRCRAFT FLIGHT CODE TABLE 8004 0 0 3 CODE TABLE 8004 0 1 008009 DETAILED PHASE OF FLIGHT CODE TABLE 8009 0 0 4 CODE TABLE 8009 0 2 008021 TIME SIGNIFICANCE CODE TABLE 8021 0 0 5 CODE TABLE 8021 0 2 008042 EXTENDED VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8042 0 0 18 FLAG TABLE 8042 0 6 008044 (VAL) CAS REGISTRY NUMBER CCITTIA5 0 0 88 CHARACTER 0 11 008192 [SIM] Number of wind velocity mean values present NUMERIC 0 0 5 NUMERIC 0 2 008193 [SIM] Number of wind velocity minimum values present NUMERIC 0 0 5 NUMERIC 0 2 008194 [SIM] Number of wind velocity maximum values present NUMERIC 0 0 5 NUMERIC 0 2 008195 [SIM] Number of wind prevalent direction values present NUMERIC 0 0 5 NUMERIC 0 2 008196 [SIM] Number of mean temperature values present NUMERIC 0 0 5 NUMERIC 0 2 008197 [SIM] Number of minimum temperature values present NUMERIC 0 0 5 NUMERIC 0 2 008198 [SIM] Number of maximum temperature values present NUMERIC 0 0 5 NUMERIC 0 2 008199 [SIM] Number of mean relative humidity values present NUMERIC 0 0 5 NUMERIC 0 2 008200 [SIM] Number of minimum relative humidity values present NUMERIC 0 0 5 NUMERIC 0 2 008201 [SIM] Number of maximum relative humidity values present NUMERIC 0 0 5 NUMERIC 0 2 008202 [SIM] Number of mean pressure values present NUMERIC 0 0 5 NUMERIC 0 2 008203 [SIM] Number of minimum pressure values present NUMERIC 0 0 5 NUMERIC 0 2 008204 [SIM] Number of maximum pressure values present NUMERIC 0 0 5 NUMERIC 0 2 008205 [SIM] Number of precipitation values present NUMERIC 0 0 5 NUMERIC 0 2 008206 [SIM] Number of leaf wetness values present NUMERIC 0 0 5 NUMERIC 0 2 008207 [SIM] Number of scalar wind velocity mean values present NUMERIC 0 0 5 NUMERIC 0 2 008208 [SIM] Number of cloud cover mean values present NUMERIC 0 0 5 NUMERIC 0 2 008209 [SIM] Number of cloud cover maximum values present NUMERIC 0 0 5 NUMERIC 0 2 008210 [SIM] Number of cloud cover minimum values present NUMERIC 0 0 5 NUMERIC 0 2 010004 PRESSURE PA -1 0 14 PA -1 5 010007 HEIGHT M 0 -1000 17 M 0 6 010008 GEOPOTENTIAL M**2/S**2 0 -10000 20 M**2/S**2 0 7 010009 GEOPOTENTIAL HEIGHT GPM 0 -1000 17 GPM 0 5 010051 PRESSURE REDUCED TO MEAN SEA LEVEL PA -1 0 14 PA -1 5 010052 ALTIMETER SETTING (QNH) PA -1 0 14 PA -1 5 010060 PRESSURE CHANGE PA -1 -1024 11 PA -1 4 010063 CHARACTERISTIC OF PRESSURE TENDENCY CODE TABLE 10063 0 0 4 CODE TABLE 10063 0 2 010197 ANEMOMETER HEIGHT M 0 0 9 M 0 3 011001 WIND DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011002 WIND SPEED M/S 1 0 12 M/S 1 4 011003 U-COMPONENT M/S 1 -4096 13 M/S 1 4 011004 V-COMPONENT M/S 1 -4096 13 M/S 1 4 011005 W-COMPONENT PA/S 1 -512 10 PA/S 1 4 011006 W-COMPONENT M/S 2 -4096 13 M/S 2 4 011016 EXTREME COUNTERCLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011017 EXTREME CLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011031 DEGREE OF TURBULENCE CODE TABLE 11031 0 0 4 CODE TABLE 11031 0 2 011036 MAXIMUM DERIVED EQUIVALENT VERTICAL GUST SPEED M/S 1 0 10 M/S 1 4 011037 TURBULENCE INDEX CODE TABLE 11037 0 0 6 CODE TABLE 11037 0 2 011039 EXTENDED TIME OF OCCURRENCE OF PEAK EDDY DISSIPATION RATE CODE TABLE 11039 0 0 6 CODE TABLE 11039 0 2 011041 MAXIMUM WIND GUST SPEED M/S 1 0 12 M/S 1 4 011043 MAXIMUM WIND GUST DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011050 STANDARD DEVIATION OF HORIZONTAL WIND SPEED M/S 1 0 12 M/S 1 4 011061 ABSOLUTE WIND SHEAR IN 1 KM LAYER BELOW M/S 1 0 12 M/S 1 4 011062 ABSOLUTE WIND SHEAR IN 1 KM LAYER ABOVE M/S 1 0 12 M/S 1 4 011075 MEAN TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 M**(2/3)/S 2 3 011076 PEAK TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 M**(2/3)/S 2 3 011077 REPORTING INTERVAL OR AVERAGING TIME FOR EDDY DISSIPATION RATE S 0 0 12 S 0 4 011192 [SIM] W-component terrain following M/S 2 -4096 13 M/S 2 4 011193 [SIM] Stability class NUMERIC 0 0 4 NUMERIC 0 2 011194 [SIM] Friction velocity (calmet) M/S 3 0 14 M/S 3 4 011195 [SIM] Mixing height (calmet) M 0 0 12 M 0 4 011196 [SIM] Obukov lenght (calmet) M 1 -100000 15 M 1 5 011197 [SIM] Convective velocitiy scale (calmet) M/S 3 0 14 M/S 3 4 011198 [SIM] SQRT(2*TKE) M/S 4 0 20 M/S 4 6 011199 [SIM] Surface Roughness M 3 0 14 M 1 4 011200 [SIM] U-component of momentum flux N/M**2 4 -524288 20 N/M**2 4 6 011201 [SIM] V-component of momentum flux N/M**2 4 -524288 20 N/M**2 4 6 011202 [SIM] Friction velocity (diagmet) M/S 3 0 14 M/S 3 4 011203 [SIM] Mixing height (diagmet) M 0 0 12 M 0 4 011204 [SIM] Obukov lenght (diagmet) M 1 -100000 15 M 1 5 011205 [SIM] Convective velocitiy scale (diagmet) M/S 3 0 14 M/S 3 4 011206 [SIM] Friction velocity (COSMO) M/S 3 0 14 M/S 3 4 011207 [SIM] Obukov lenght (COSMO) M 1 -100000 15 M 1 5 011208 [SIM] Distance covered by the hourly mean wind M 0 0 23 M 0 7 012001 TEMPERATURE/AIR TEMPERATURE K 1 0 12 C 1 3 012003 DEW-POINT TEMPERATURE K 1 0 12 C 1 3 012030 SOIL TEMPERATURE K 1 0 12 C 1 3 012049 Temperature change over specified period K 0 -30 6 C 0 2 012061 SKIN TEMPERATURE K 1 0 12 K 1 4 012063 BRIGHTNESS TEMPERATURE K 1 0 12 K 1 4 012101 TEMPERATURE/DRY-BULB TEMPERATURE K 2 0 16 K 2 5 012102 WET-BULB TEMPERATURE K 2 0 16 C 2 4 012103 DEW-POINT TEMPERATURE K 2 0 16 K 2 5 012121 GROUND MINIMUM TEMPERATURE K 2 0 16 C 2 4 012131 SNOW TEMPERATURE K 2 0 16 C 2 4 012192 POTENTIAL TEMPERATURE K 2 0 16 K 2 5 012193 PSEUDO-EQUIVALENT POTENTIAL TEMPERATURE K 2 0 16 K 2 5 012194 [SIM] Air density KG/M**3 6 0 20 KG/M**3 6 6 013001 SPECIFIC HUMIDITY KG/KG 5 0 14 KG/KG 5 5 013002 MIXING RATIO KG/KG 5 0 14 KG/KG 5 5 013003 RELATIVE HUMIDITY % 0 0 7 % 0 3 013011 TOTAL PRECIPITATION / TOTAL WATER EQUIVALENT KG/M**2 1 -1 14 KG/M**2 1 5 013012 DEPTH OF FRESH SNOW M 2 -2 12 M 2 4 013013 TOTAL SNOW DEPTH M 3 -20 20 M 3 6 013031 EVAPOTRANSPIRATION KG/M**2 1 0 7 KG/M**2 0 3 013033 EVAPORATION/EVAPOTRANSPIRATION KG/M**2 1 0 10 KG/M**2 1 4 013081 WATER CONDUCTIVITY S/M 3 0 14 S/M 3 4 013082 WATER TEMPERATURE K 1 0 12 K 1 4 013192 [SIM] Cloud liquid water content KG/KG 8 0 27 KG/KG 8 8 013193 [SIM] Cloud ice content KG/KG 8 0 27 KG/KG 8 8 013194 [SIM] Water table depth M 3 0 18 M 3 6 013195 [SIM] Precipitating liquid water KG/KG 8 0 27 KG/KG 8 8 013196 [SIM] Precipitating ice KG/KG 8 0 27 KG/KG 8 8 013197 [SIM] Total precipitating water+ice KG/KG 8 0 27 KG/KG 8 8 013198 [SIM] Total liquid water (cloud+precipitating) KG/KG 8 0 27 KG/KG 8 8 013199 [SIM] Total ice (cloud+precipitating) KG/KG 8 0 27 KG/KG 8 8 013200 [SIM] Grid-scale liquid precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013201 [SIM] Grid-scale snowfall KG/M**2 1 -1 14 KG/M**2 1 5 013202 [SIM] Convective liquid precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013203 [SIM] Convective snowfall KG/M**2 1 -1 14 KG/M**2 1 5 013204 [SIM] Total convective precipitation (liquid + snow) KG/M**2 1 -1 14 KG/M**2 1 5 013205 [SIM] Snowfall (grid-scale + convective) KG/M**2 1 -1 14 KG/M**2 1 5 013206 [SIM] Soil water content KG/M**2 1 0 14 KG/M**2 1 5 013210 [SIM] Penetration of the probe in the snow M 2 0 9 M 2 3 013212 [SIM] Leaf wetness duration S -1 0 24 S -1 7 013215 [SIM] River level M 2 -100000 18 M 2 6 013216 [SIM] Hourly precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013217 [SIM] 5 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013218 [SIM] 10 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013219 [SIM] 15 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013220 [SIM] 20 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013221 [SIM] 30 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013222 [SIM] 180 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013223 [SIM] 360 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013224 [SIM] 720 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013225 [SIM] 1440 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013226 [SIM] River discharge M**3/S 2 0 21 M**3/S 2 7 013227 [SIM] Soil volumetric water content % 1 0 10 % 1 4 013228 [SIM] Piezometric level M 3 0 18 M 3 6 013229 [SIM] Density of snow KG/M**3 1 0 14 KG/M**3 1 5 013230 [SIM] Convective Available Potential Energy (CAPE) J/KG 1 0 17 J/KG 1 5 014002 Long-wave radiation, integrated over period specified J M-2 -3 -65536 17 J M-2 -3 5 014004 Short-wave radiation, integrated over period specified J M-2 -3 -65536 17 J M-2 -3 5 014016 NET RADIATION J/M**2 -4 -16384 15 J/M**2 -4 5 014017 INSTANTANEOUS LONG-WAVE RADIATION (incoming) W/M**2 0 -2048 12 W/M**2 0 4 014018 INSTANTANEOUS SHORT-WAVE RADIATION (incoming) W/M**2 0 -2048 12 W/M**2 -3 4 014019 SURFACE ALBEDO % 0 0 7 % 0 3 014021 GLOBAL SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 J/M**2 -4 5 014028 Global solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 J M-2 -2 6 014029 Diffuse solar radiation (high accuracy), integrated over period J M-2 -2 0 20 J M-2 -2 6 014030 Direct solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 J M-2 -2 6 014031 TOTAL SUNSHINE MINUTE 0 0 11 MINUTE 0 4 014192 [SIM] Instantenous sensible heat flux W/m**2 0 -1024 11 W/M**2 0 4 014193 [SIM] Instantenous latent heat flux W/m**2 0 -1024 11 W/M**2 0 4 014194 [SIM] Instantenous direct solar radiation W/M**2 0 -2048 12 W/M**2 -3 4 014195 [SIM] Instantenous diffuse solar radiation W/M**2 0 -2048 12 W/M**2 -3 4 014196 [SIM] INSTANTANEOUS NET LONG-WAVE RADIATION W/M**2 0 -2048 12 W/M**2 0 4 014197 [SIM] INSTANTANEOUS NET SHORT-WAVE RADIATION W/M**2 0 -2048 12 W/M**2 -3 4 014198 [SIM] Visible radiation (downward) W/M**2 3 -50000 21 W/M**2 3 7 014199 [SIM] Visible radiation (upward) W/M**2 3 -50000 21 W/M**2 3 7 014200 [SIM] Infrared radiation (downward) W/M**2 3 0 20 W/M**2 3 7 014201 [SIM] Infrared radiation (upward) W/M**2 3 0 20 W/M**2 3 7 015192 [SIM] NO Concentration KG/M**3 10 0 20 KG/M**3 10 6 015193 [SIM] NO2 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015194 [SIM] O3 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015195 [SIM] PM10 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015196 [SIM] CO Concentration KG/M**3 10 0 20 KG/M**3 10 6 015197 [SIM] SO2 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015198 [SIM] PM2.5 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015199 [SIM] NOY Concentration KG/M**3 10 0 20 KG/M**3 10 6 015200 [SIM] HCNM Concentration KG/M**3 10 0 20 KG/M**3 10 6 015201 [SIM] ALDE Concentration KG/M**3 10 0 20 KG/M**3 10 6 015202 [SIM] PM5 Concentration (tot. aerosol < 5 ug) KG/M**3 10 0 20 KG/M**3 10 6 015203 [SIM] PM1 Concentration (tot. aerosol < 1.25 ug) KG/M**3 10 0 20 KG/M**3 10 6 015204 [SIM] PM06 Concentration (tot. aerosol < 0.6 ug) KG/M**3 10 0 20 KG/M**3 10 6 015205 [SIM] PM03 Concentration (tot. aerosol < 0.3 ug) KG/M**3 10 0 20 KG/M**3 10 6 015206 [SIM] PM015 Concentration (tot. aerosol < 0.15 ug) KG/M**3 10 0 20 KG/M**3 10 6 015207 [SIM] PM008 Concentration (tot. aerosol < 0.08 ug) KG/M**3 10 0 20 KG/M**3 10 6 015208 [SIM] Concentration of primary particulate matter in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015209 [SIM] Concentration of sulfate in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015210 [SIM] Concentration of nitrate in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015211 [SIM] Concentration of ammonium in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015212 [SIM] Concentration of black carbon in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015213 [SIM] Concentration of organic carbon in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015214 [SIM] Concentration of dust in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015215 [SIM] Concentration of anthrop. A1D in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015216 [SIM] Concentration of anthrop. BmP in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015217 [SIM] Concentration of biogenic A1D in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015218 [SIM] Concentration of biogenic BmP in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015219 [SIM] Concentration of water in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015220 [SIM] Concentration of sea salt in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015221 [SIM] Concentration of secondary organic aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015222 [SIM] Total concentration of primary aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015223 [SIM] Total concentration of secondary aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015224 [SIM] Uncertainity in O3 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015225 [SIM] Uncertainity in PM10 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015226 [SIM] Uncertainity in NO2 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015227 [SIM] Uncertainity in PM2.5 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015228 [SIM] NH3 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015229 [SIM] Concentration of primary part. matter in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015230 [SIM] Concentration of sulfate in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015231 [SIM] Concentration of nitrate in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015232 [SIM] Concentration of ammonium in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015233 [SIM] Concentration of anthrop. sec. org. in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015234 [SIM] Concentration of biogenic sec. org. in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015235 [SIM] Concentration of ISOPA1 in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015236 [SIM] C6H6 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015237 [SIM] Concentration of anthropogenic aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015238 [SIM] Concentration of biogenic aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015239 [SIM] Concentration of anthropogenic aerosol in PM2.5 KG/M**3 10 0 20 KG/M**3 10 6 015240 [SIM] Concentration of biogenic aerosol in PM2.5 KG/M**3 10 0 20 KG/M**3 10 6 015241 [SIM] Aerosol Optical Thickness NUMERIC 4 0 15 NUMERIC 4 5 020001 HORIZONTAL VISIBILITY M -1 0 13 M -1 4 020003 PRESENT WEATHER (SEE NOTE 1) CODE TABLE 20003 0 0 9 CODE TABLE 20003 0 3 020004 PAST WEATHER (1) (SEE NOTE 2) CODE TABLE 20004 0 0 5 CODE TABLE 20004 0 2 020005 PAST WEATHER (2) (SEE NOTE 2) CODE TABLE 20005 0 0 5 CODE TABLE 20005 0 2 020009 GENERAL WEATHER INDICATOR (TAF/METAR) CODE TABLE 20009 0 0 4 CODE TABLE 20009 0 2 020010 CLOUD COVER (TOTAL) % 0 0 7 % 0 3 020011 CLOUD AMOUNT CODE TABLE 20011 0 0 4 CODE TABLE 20011 0 2 020012 CLOUD TYPE CODE TABLE 20012 0 0 6 CODE TABLE 20012 0 2 020013 HEIGHT OF BASE OF CLOUD M 0 -400 17 M 0 5 020017 CLOUD TOP DESCRIPTION CODE TABLE 20017 0 0 4 CODE TABLE 20017 0 2 020019 SIGNIFICANT PRESENT OR FORECAST WEATHER CCITTIA5 0 0 72 CHARACTER 0 9 020021 TYPE OF PRECIPITATION FLAG TABLE 20021 0 0 30 FLAG TABLE 20021 0 10 020031 ICE DEPOSIT (THICKNESS) M 2 0 7 M 2 3 020032 RATE OF ICE ACCRETION CODE TABLE 20032 0 0 3 CODE TABLE 20032 0 1 020033 CAUSE OF ICE ACCRETION FLAG TABLE 20033 0 0 4 FLAG TABLE 20033 0 2 020034 SEA ICE CONCENTRATION CODE TABLE 20034 0 0 5 CODE TABLE 20034 0 2 020035 AMOUNT AND TYPE OF ICE CODE TABLE 20035 0 0 4 CODE TABLE 20035 0 2 020036 ICE SITUATION CODE TABLE 20036 0 0 5 CODE TABLE 20036 0 2 020037 ICE DEVELOPMENT CODE TABLE 20037 0 0 5 CODE TABLE 20037 0 2 020038 BEARING OF ICE EDGE (SEE NOTE 3) DEGREE TRUE 0 0 12 DEGREE TRUE 0 3 020042 AIRFRAME ICING PRESENT CODE TABLE 20042 0 0 2 CODE TABLE 20042 0 1 020043 PEAK LIQUID WATER CONTENT KG/M**3 4 0 7 KG/M**3 4 2 020044 AVERAGE LIQUID WATER CONTENT KG/M**3 4 0 7 KG/M**3 4 2 020045 SUPERCOOLED LARGE DROPLET (SLD) CONDITIONS CODE TABLE 20045 0 0 2 CODE TABLE 20045 0 2 020062 STATE OF THE GROUND (WITH OR WITHOUT SNOW) CODE TABLE 20062 0 0 5 CODE TABLE 20062 0 2 020192 [SIM] Presence of rain > 1mm BOOLEAN 0 0 1 BOOLEAN 0 1 020193 [SIM] Cloud type (METAR) CCITTIA5 0 0 16 CHARACTER 0 2 020194 [SIM] Presence of shower BOOLEAN 0 0 1 BOOLEAN 0 1 020195 [SIM] Presence of hail BOOLEAN 0 0 1 BOOLEAN 0 1 020196 [SIM] Presence of thunderstorm BOOLEAN 0 0 1 BOOLEAN 0 1 020197 [SIM] Presence of snow BOOLEAN 0 0 1 BOOLEAN 0 1 020198 [SIM] Presence of frost BOOLEAN 0 0 1 BOOLEAN 0 1 020199 [SIM] Presence of dew BOOLEAN 0 0 1 BOOLEAN 0 1 020200 [SIM] Presence of fog BOOLEAN 0 0 1 BOOLEAN 0 1 020201 [SIM] Presence of water-spout BOOLEAN 0 0 1 BOOLEAN 0 1 020202 [SIM] State of the ground with snow CODE TABLE 0 0 5 CODE TABLE 0 2 022001 DIRECTION OF WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022002 DIRECTION OF WIND WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022003 DIRECTION OF SWELL WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022004 DIRECTION OF CURRENT DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022011 PERIOD OF WAVES S 0 0 6 S 0 2 022012 PERIOD OF WIND WAVES S 0 0 6 S 0 2 022013 PERIOD OF SWELL WAVES S 0 0 6 S 0 2 022021 HEIGHT OF WAVES M 1 0 10 M 1 4 022022 HEIGHT OF WIND WAVES M 1 0 10 M 1 4 022023 HEIGHT OF SWELL WAVES M 1 0 10 M 1 4 022031 SPEED OF CURRENT M/S 2 0 13 M/S 2 4 022032 SPEED OF SEA SURFACE CURRENT M/S 2 0 13 M/S 2 4 022037 Tidal elevation with respect to national land datum M 3 -10000 15 M 3 5 022038 Tidal elevation with respect to local chart datum M 3 -10000 15 M 3 5 022042 SEA/WATER TEMPERATURE K 1 0 12 K 1 4 022043 SEA/WATER TEMPERATURE K 2 0 15 K 2 5 022049 SEA-SURFACE TEMPERATURE K 2 0 15 K 2 5 022070 SIGNIFICANT WAVE HEIGHT M 2 0 13 M 2 4 022071 SPECTRAL PEAK WAVE PERIOD S 1 0 9 S 1 3 022074 AVERAGE WAVE PERIOD S 1 0 9 S 1 3 022192 [SIM] Current X component M/S 2 0 13 M/S 2 4 022193 [SIM] Current Y component M/S 2 0 13 M/S 2 4 023192 [SIM] Dry deposition of H2SO4 MOL/M**2 5 0 20 MOL/M**3 5 6 023193 [SIM] Wet deposition of H2SO4 MOL/M**2 5 0 20 MOL/M**3 5 6 023194 [SIM] Dry deposition of NH4 MOL/M**2 5 0 20 MOL/M**3 5 6 023195 [SIM] Wet deposition of NH4 MOL/M**2 5 0 20 MOL/M**3 5 6 023196 [SIM] Dry deposition of HNO3 MOL/M**2 5 0 20 MOL/M**3 5 6 023197 [SIM] Wet deposition of HNO3 MOL/M**2 5 0 20 MOL/M**3 5 6 023198 [SIM] Solid transport by river KG/S 2 0 24 KG/S 2 8 025076 LOG-10 OF (TEMP-RAD CENTRAL WAVENUMBER) FOR ATOVS LOGM-1 8 0 30 LOGM-1 8 10 029192 [SIM] Land fraction % 1 0 10 % 1 4 031000 SHORT DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 1 NUMERIC 0 1 031001 DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031011 DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031012 EXTENDED DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031021 ASSOCIATED FIELD SIGNIFICANCE CODE TABLE 31021 0 0 6 CODE TABLE 31021 0 2 031031 DATA PRESENT INDICATOR FLAG TABLE 31031 0 0 1 FLAG TABLE 31031 0 1 033002 QUALITY INFORMATION CODE TABLE 33002 0 0 2 CODE TABLE 33002 0 1 033003 QUALITY INFORMATION CODE TABLE 33003 0 0 3 CODE TABLE 33003 0 1 033005 QUALITY INFORMATION (AWS DATA) FLAG TABLE 33005 0 0 30 FLAG TABLE 33005 0 10 033006 INTERNAL MEASUREMENT STATUS INFORMATION (AWS) CODE TABLE 33006 0 0 3 CODE TABLE 33006 0 1 033007 PER CENT CONFIDENCE % 0 0 7 % 0 3 033015 DATA QUALITY CHECK INDICATOR CODE TABLE 33015 0 0 6 CODE TABLE 33015 0 2 033020 QUALITY CONTROL INDICATION OF FOLLOWING VALUE CODE TABLE 33020 0 0 3 CODE TABLE 33020 0 1 033021 QUALITY OF FOLLOWING VALUE CODE TABLE 33021 0 0 2 CODE TABLE 33021 0 1 033022 QUALITY OF BUOY SATELLITE TRANSMISSION CODE TABLE 33022 0 0 2 CODE TABLE 33022 0 1 033023 QUALITY OF BUOY LOCATION CODE TABLE 33023 0 0 2 CODE TABLE 33023 0 1 033024 STATION ELEVATION QUALITY MARK (FOR MOBILE STATIONS) CODE TABLE 33024 0 0 4 CODE TABLE 33024 0 2 033025 ACARS INTERPOLATED VALUES CODE TABLE 33025 0 0 3 CODE TABLE 33025 0 1 033026 MOISTURE QUALITY CODE TABLE 33026 0 0 6 CODE TABLE 33026 0 2 033027 LOCATION QUALITY CLASS (RANGE OF RADIUS OF 66 % CONFIDENCE) CODE TABLE 33027 0 0 3 CODE TABLE 33027 0 1 033030 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 33030 0 0 24 FLAG TABLE 33030 0 8 033031 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 33031 0 0 24 FLAG TABLE 33031 0 8 033032 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 33032 0 0 24 FLAG TABLE 33032 0 8 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS FLAG TABLE 33033 0 0 24 FLAG TABLE 33033 0 8 033035 MANUAL/AUTOMATIC QUALITY CONTROL CODE TABLE 33035 0 0 4 CODE TABLE 33035 0 2 033036 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 % 0 3 033037 WIND CORRELATION ERROR FLAG TABLE 33037 0 0 20 FLAG TABLE 33037 0 7 033038 QUALITY FLAGS FOR GROUND-BASED GNSS DATA FLAG TABLE 33038 0 0 10 FLAG TABLE 33038 0 4 033040 CONFIDENCE INTERVAL % 0 0 7 PERCENT 0 3 033041 ATTRIBUTE OF FOLLOWING VALUE CODE TABLE 33041 0 0 2 CODE TABLE 33041 0 1 033050 GLOBAL GTSPP QUALITY FLAG CODE TABLE 33050 0 0 4 CODE TABLE 33050 0 2 033192 [SIM] Climatological and consistency check % 0 0 7 PERCENT 0 3 033193 [SIM] Time consistency % 0 0 7 PERCENT 0 3 033194 [SIM] Space consistency % 0 0 7 PERCENT 0 3 033195 [SIM] MeteoDB variable ID NUMERIC 0 0 24 NUMERIC 0 8 033196 [SIM] Data has been invalidated CODE TABLE 33196 0 0 2 CODE TABLE 33196 0 1 033197 [SIM] Manual replacement in substitution CODE TABLE 33197 0 0 2 CODE TABLE 33197 0 1 033198 [SIM] Observation increment NUMERIC 4 -1073741823 31 NUMERIC 4 10 033201 [SIM] Kalman coefficient, state vector (s.v.) x1 NUMERIC 4 -1073741823 31 NUMERIC 4 10 033202 [SIM] Kalman coefficient, state vector (s.v.) x2 NUMERIC 4 -1073741823 31 NUMERIC 4 10 033203 [SIM] Kalman coefficient, s.v. error covariance matrix(1,1) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033204 [SIM] Kalman coefficient, s.v. error covariance matrix(1,2) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033205 [SIM] Kalman coefficient, s.v. error covariance matrix(2,1) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033206 [SIM] Kalman coefficient, s.v. error covariance matrix(2,2) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033207 [SIM] Kalman observation sequential counter NUMERIC 0 -127 8 NUMERIC 0 3 033208 [SIM] Kalman osservation missing counter NUMERIC 0 -127 8 NUMERIC 0 3 033209 [SIM] Normalized Density Index % 0 0 7 PERCENT 0 3 048001 [SIM] Graminacee_Graminacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048002 [SIM] Betulacee_Ontano nero POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048003 [SIM] Betulacee_Betulla POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048004 [SIM] Betulacee_Betulacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048005 [SIM] Composite_Ambrosia POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048006 [SIM] Composite_Artemisia POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048007 [SIM] Composite_Composite indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048008 [SIM] Corilacee_Nocciolo POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048009 [SIM] Corilacee_Carpino bianco -Carpino nero POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048010 [SIM] Corilacee_Corilacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048011 [SIM] Fagacee_Castagno POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048012 [SIM] Fagacee_Faggio POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048013 [SIM] Fagacee_Quercia POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048014 [SIM] Fagacee_Fagacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048015 [SIM] Oleacee_Olivo POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048016 [SIM] Oleacee_Frassino POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048017 [SIM] Oleacee_Oleacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048018 [SIM] Plantaginacee_Plantaginacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048019 [SIM] Urticacee_Urticacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048020 [SIM] Cupressacee - Taxacee indistinte_Cipresso comune POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048021 [SIM] Cupressacee - Taxacee indistinte_Cupressacee - Taxacee ind POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048022 [SIM] Chenopodiacee - Amarantacee Indistinte_Amaranto POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048023 [SIM] Chenopodiacee - Amarantacee Indistinte_Chenopodiacee - Ama POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048024 [SIM] Poligonacee_Poligonacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048025 [SIM] Euphorbiacee_Euforbiacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048026 [SIM] Mirtacee_Mirtacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048027 [SIM] Ulmacee_Bagolaro comune POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048028 [SIM] Ulmacee_Olmo campestre POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048029 [SIM] Ulmacee_Ulmacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048030 [SIM] Platanacee_Platanacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048031 [SIM] Aceraceae_Aceracee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048032 [SIM] Pinacee_Pinacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048033 [SIM] Salicacee_Salice comune POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048034 [SIM] Salicacee_Pioppo POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048035 [SIM] Salicacee_Salicacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048036 [SIM] Ciperacee_Ciperacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048037 [SIM] Juglandacee_Juglandacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048038 [SIM] Ippocastanacee_Ippocastanacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048039 [SIM] Spore fungine_Alternaria POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048040 [SIM] Spore fungine_Botrytis POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048041 [SIM] Spore fungine_Stemphylium POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048042 [SIM] Spore fungine_Cladosporium POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048043 [SIM] Spore fungine_Epicoccum POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048044 [SIM] Altri Pollini / Non Identificati_Altri pollini identificat POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048045 [SIM] Altri Pollini / Non Identificati_Pollini non identificati POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048046 [SIM] Altre Spore / Non identificati_Altre spore fungine POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048047 [SIM] Altre Spore / Non identificati_Spore fungine non identific POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048048 [SIM] Graminacee_Graminacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048049 [SIM] Plantaginacee_Plantaginacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048050 [SIM] Urticacee_Urticacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048051 [SIM] Poligonacee_Poligonacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048052 [SIM] Euphorbiacee_Euforbiacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048053 [SIM] Mirtacee_Mirtacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048054 [SIM] Platanacee_Platanacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048055 [SIM] Aceraceae_Aceracee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048056 [SIM] Pinacee_Pinacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048057 [SIM] Ciperacee_Ciperacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048058 [SIM] Juglandacee_Juglandacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048059 [SIM] Ippocastanacee_Ippocastanacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048060 [SIM] Oleacee_Ligustro POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048128 [SIM] Conta Graminacee_Graminacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048129 [SIM] Conta Betulacee_Ontano nero NUMERIC 0 0 20 NUMERIC 0 7 048130 [SIM] Conta Betulacee_Betulla NUMERIC 0 0 20 NUMERIC 0 7 048131 [SIM] Conta Betulacee_Betulacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048132 [SIM] Conta Composite_Ambrosia NUMERIC 0 0 20 NUMERIC 0 7 048133 [SIM] Conta Composite_Artemisia NUMERIC 0 0 20 NUMERIC 0 7 048134 [SIM] Conta Composite_Composite indistinte NUMERIC 0 0 20 NUMERIC 0 7 048135 [SIM] Conta Corilacee_Nocciolo NUMERIC 0 0 20 NUMERIC 0 7 048136 [SIM] Conta Corilacee_Carpino bianco -Carpino nero NUMERIC 0 0 20 NUMERIC 0 7 048137 [SIM] Conta Corilacee_Corilacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048138 [SIM] Conta Fagacee_Castagno NUMERIC 0 0 20 NUMERIC 0 7 048139 [SIM] Conta Fagacee_Faggio NUMERIC 0 0 20 NUMERIC 0 7 048140 [SIM] Conta Fagacee_Quercia NUMERIC 0 0 20 NUMERIC 0 7 048141 [SIM] Conta Fagacee_Fagacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048142 [SIM] Conta Oleacee_Olivo NUMERIC 0 0 20 NUMERIC 0 7 048143 [SIM] Conta Oleacee_Frassino NUMERIC 0 0 20 NUMERIC 0 7 048144 [SIM] Conta Oleacee_Oleacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048145 [SIM] Conta Plantaginacee_Plantaginacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048146 [SIM] Conta Urticacee_Urticacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048147 [SIM] Conta Cupressacee - Taxacee indistinte_Cipresso comune NUMERIC 0 0 20 NUMERIC 0 7 048148 [SIM] Conta Cupressacee - Taxacee indistinte_Cupressacee - Taxac NUMERIC 0 0 20 NUMERIC 0 7 048149 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Amaranto NUMERIC 0 0 20 NUMERIC 0 7 048150 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Chenopodiacee NUMERIC 0 0 20 NUMERIC 0 7 048151 [SIM] Conta Poligonacee_Poligonacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048152 [SIM] Conta Euphorbiacee_Euforbiacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048153 [SIM] Conta Mirtacee_Mirtacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048154 [SIM] Conta Ulmacee_Bagolaro comune NUMERIC 0 0 20 NUMERIC 0 7 048155 [SIM] Conta Ulmacee_Olmo campestre NUMERIC 0 0 20 NUMERIC 0 7 048156 [SIM] Conta Ulmacee_Ulmacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048157 [SIM] Conta Platanacee_Platanacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048158 [SIM] Conta Aceraceae_Aceracee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048159 [SIM] Conta Pinacee_Pinacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048160 [SIM] Conta Salicacee_Salice comune NUMERIC 0 0 20 NUMERIC 0 7 048161 [SIM] Conta Salicacee_Pioppo NUMERIC 0 0 20 NUMERIC 0 7 048162 [SIM] Conta Salicacee_Salicacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048163 [SIM] Conta Ciperacee_Ciperacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048164 [SIM] Conta Juglandacee_Juglandacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048165 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048166 [SIM] Conta Spore fungine_Alternaria NUMERIC 0 0 20 NUMERIC 0 7 048167 [SIM] Conta Spore fungine_Botrytis NUMERIC 0 0 20 NUMERIC 0 7 048168 [SIM] Conta Spore fungine_Stemphylium NUMERIC 0 0 20 NUMERIC 0 7 048169 [SIM] Conta Spore fungine_Cladosporium NUMERIC 0 0 20 NUMERIC 0 7 048170 [SIM] Conta Spore fungine_Epicoccum NUMERIC 0 0 20 NUMERIC 0 7 048171 [SIM] Conta Altri Pollini / Non Identificati_Altri pollini ident NUMERIC 0 0 20 NUMERIC 0 7 048172 [SIM] Conta Altri Pollini / Non Identificati_Pollini non identif NUMERIC 0 0 20 NUMERIC 0 7 048173 [SIM] Conta Altre Spore / Non identificati_Altre spore fungine NUMERIC 0 0 20 NUMERIC 0 7 048174 [SIM] Conta Altre Spore / Non identificati_Spore fungine non ide NUMERIC 0 0 20 NUMERIC 0 7 048175 [SIM] Conta Graminacee_Graminacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048176 [SIM] Conta Plantaginacee_Plantaginacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048177 [SIM] Conta Urticacee_Urticacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048178 [SIM] Conta Poligonacee_Poligonacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048179 [SIM] Conta Euphorbiacee_Euforbiacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048180 [SIM] Conta Mirtacee_Mirtacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048181 [SIM] Conta Platanacee_Platanacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048182 [SIM] Conta Aceraceae_Aceracee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048183 [SIM] Conta Pinacee_Pinacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048184 [SIM] Conta Ciperacee_Ciperacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048185 [SIM] Conta Juglandacee_Juglandacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048186 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048187 [SIM] Conta Oleacee_Ligustro NUMERIC 0 0 20 NUMERIC 0 7 dballe-7.7/tables/B990204.txt0000644000175000017500000023620212652630120012421 00000000000000 001001 WMO BLOCK NUMBER NUMERIC 0 0 7 NUMERIC 0 2 001002 WMO STATION NUMBER NUMERIC 0 0 10 NUMERIC 0 3 001006 AIRCRAFT FLIGHT NUMBER CCITTIA5 0 0 64 CHARACTER 0 8 001007 SATELLITE IDENTIFIER CODE TABLE 1007 0 0 10 CODE TABLE 1007 0 3 001008 AIRCRAFT REGISTRATION NUMBER OR OTHER IDENTIFICATION CCITTIA5 0 0 64 CHARACTER 0 8 001011 SHIP OR MOBILE LAND STATION IDENTIFIER CCITTIA5 0 0 72 CHARACTER 0 9 001012 DIRECTION OF MOTION OF MOVING OBSERVING PLATFORM** DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 001013 SPEED OF MOTION OF MOVING OBSERVING PLATFORM* M/S 0 0 10 M/S 0 3 001019 LONG STATION OR SITE NAME CCITTIA5 0 0 256 CHARACTER 0 32 001023 OBSERVATION SEQUENCE NUMBER NUMERIC 0 0 9 NUMERIC 0 3 001033 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE CODE TABLE 001033 0 0 8 CODE TABLE 001033 0 3 001034 IDENTIFICATION OF ORIGINATING/GENERATING SUB-CENTRE CODE TABLE 001034 0 0 8 CODE TABLE 001034 0 3 001063 ICAO LOCATION INDICATOR CCITTIA5 0 0 64 CHARACTER 0 8 001192 [SIM] MeteoDB station ID NUMERIC 0 0 24 NUMERIC 0 8 001193 [SIM] Report code NUMERIC 0 0 16 NUMERIC 0 5 001194 [SIM] Report mnemonic CCITTIA5 0 0 128 CHARACTER 0 16 001212 AIR QUALITY OBSERVING STATION LOCAL CODE CCITTIA5 0 0 56 CHARACTER 0 7 001213 AIRBASE AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 56 CHARACTER 0 7 001214 GEMS AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 48 CHARACTER 0 6 001215 AIR QUALITY OBSERVING STATION DOMINANT EMISSION SOURCE CODE TABLE 001215 0 0 3 CODE TABLE 001215 0 1 001216 AIR QUALITY OBSERVING STATION AREA TYPE CODE TABLE 001216 0 0 3 CODE TABLE 001216 0 1 001217 AIR QUALITY OBSERVING STATION TERRAIN TYPE CODE TABLE 001217 0 0 4 CODE TABLE 001217 0 2 002001 TYPE OF STATION CODE TABLE 2001 0 0 2 CODE TABLE 2001 0 1 002002 TYPE OF INSTRUMENTATION FOR WIND MEASUREMENT FLAG TABLE 2002 0 0 4 FLAG TABLE 2002 0 2 002003 TYPE OF MEASURING EQUIPMENT USED CODE TABLE 2003 0 0 4 CODE TABLE 2003 0 2 002004 TYPE OF INSTRUMENTATION FOR EVAPORATION MEASUREMENT OR TYPE OF C CODE TABLE 2004 0 0 4 CODE TABLE 2004 0 2 002005 PRECISION OF TEMPERATURE OBSERVATION K 2 0 7 K 2 3 002011 RADIOSONDE TYPE CODE TABLE 2011 0 0 8 CODE TABLE 2011 0 3 002012 RADIOSONDE COMPUTATIONAL METHOD CODE TABLE 2012 0 0 4 CODE TABLE 2012 0 2 002013 SOLAR AND INFRARED RADIATION CORRECTION CODE TABLE 2013 0 0 4 CODE TABLE 2013 0 2 002014 TRACKING TECHNIQUE/STATUS OF SYSTEM USED CODE TABLE 2014 0 0 7 CODE TABLE 2014 0 3 002038 METHOD OF WATER TEMPERATURE AND/OR SALINITY MEASUREMENT CODE TABLE 2038 0 0 4 CODE TABLE 2038 0 2 002039 METHOD OF WET-BULB TEMPERATURE MEASUREMENT CODE TABLE 2039 0 0 3 CODE TABLE 2039 0 1 002048 SATELLITE SENSOR INDICATOR CODE TABLE 2048 0 0 4 CODE TABLE 2048 0 2 002061 AIRCRAFT NAVIGATIONAL SYSTEM CODE TABLE 2061 0 0 3 CODE TABLE 2061 0 1 002062 TYPE OF AIRCRAFT DATA RELAY SYSTEM CODE TABLE 2062 0 0 4 CODE TABLE 2062 0 2 002063 AIRCRAFT ROLL ANGLE DEGREE 2 -18000 16 DEGREE 2 5 002064 AIRCRAFT ROLL ANGLE QUALITY CODE TABLE 2064 0 0 2 CODE TABLE 2064 0 1 002070 ORIGINAL SPECIFICATION OF LATITUDE/LONGITUDE CODE TABLE 2070 0 0 4 CODE TABLE 2070 0 2 002121 MEAN FREQUENCY Hz -8 0 7 Hz -8 3 002125 PULSE REPETITION FREQUENCY Hz -1 0 8 Hz -1 3 004001 YEAR YEAR 0 0 12 YEAR 0 4 004002 MONTH MONTH 0 0 4 MONTH 0 2 004003 DAY DAY 0 0 6 DAY 0 2 004004 HOUR HOUR 0 0 5 HOUR 0 2 004005 MINUTE MINUTE 0 0 6 MINUTE 0 2 004006 SECOND SECOND 0 0 6 SECOND 0 2 004086 LONG TIME PERIOD OR DISPLACEMENT SECOND 0 -8192 15 SECOND 0 5 004192 [SIM] Time range type NUMERIC 0 0 10 NUMERIC 0 4 004193 [SIM] Time range P1 NUMERIC 0 -536870912 31 NUMERIC 0 10 004194 [SIM] Time range P2 NUMERIC 0 -536870912 31 NUMERIC 0 10 004195 [SIM] Temperature event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 004196 [SIM] Relative humidity event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 004197 [SIM] Wind velocity event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 004198 [SIM] Pressure event - time of occurrence MINUTE 0 0 11 MINUTE 0 4 005001 LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 005015 LATITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 005021 BEARING OR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005022 SOLAR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005040 ORBIT NUMBER NUMERIC 0 0 24 NUMERIC 0 8 005041 SCAN LINE NUMBER NUMERIC 0 0 8 NUMERIC 0 3 005043 FIELD OF VIEW NUMBER NUMERIC 0 0 8 NUMERIC 0 3 006001 LONGITUDE (HIGH ACCURACY) DEGREE 5 -18000000 26 DEGREE 5 8 006015 LONGITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -18000000 26 DEGREE 5 8 007002 HEIGHT OR ALTITUDE M -1 -40 16 M -1 5 007004 PRESSURE PA -1 0 14 PA -1 5 007007 HEIGHT M 0 -1000 17 M 0 6 007010 FLIGHT LEVEL M 0 -1024 16 FT -1 5 007024 SATELLITE ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007025 SOLAR ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007030 HEIGHT OF STATION GROUND ABOVE MEAN SEA LEVEL (SEE NOTE 3) M 1 -4000 17 M 1 5 007031 HEIGHT OF BAROMETER ABOVE MEAN SEA LEVEL (SEE NOTE 4) M 1 - 4000 17 M 1 5 007032 HEIGHT OF SENSOR ABOVE LOCAL GROUND (OR DECK OF MARINE PLATFORM) M 2 0 16 M 2 5 007192 [SIM] First level type NUMERIC 0 0 10 NUMERIC 0 4 007193 [SIM] Level L1 NUMERIC 0 -536870912 31 NUMERIC 0 10 007194 [SIM] Level L2 NUMERIC 0 -536870912 31 NUMERIC 0 10 007195 [SIM] Second level type NUMERIC 0 0 31 NUMERIC 0 4 008002 VERTICAL SIGNIFICANCE (SURFACE OBSERVATIONS) CODE TABLE 8002 0 0 6 CODE TABLE 8002 0 2 008004 PHASE OF AIRCRAFT FLIGHT CODE TABLE 8004 0 0 3 CODE TABLE 8004 0 1 008009 DETAILED PHASE OF FLIGHT CODE TABLE 8009 0 0 4 CODE TABLE 8009 0 2 008021 TIME SIGNIFICANCE CODE TABLE 8021 0 0 5 CODE TABLE 8021 0 2 008042 EXTENDED VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8042 0 0 18 FLAG TABLE 8042 0 6 008044 (VAL) CAS REGISTRY NUMBER CCITTIA5 0 0 88 CHARACTER 0 11 008192 [SIM] Number of wind velocity mean values present NUMERIC 0 0 5 NUMERIC 0 2 008193 [SIM] Number of wind velocity minimum values present NUMERIC 0 0 5 NUMERIC 0 2 008194 [SIM] Number of wind velocity maximum values present NUMERIC 0 0 5 NUMERIC 0 2 008195 [SIM] Number of wind prevalent direction values present NUMERIC 0 0 5 NUMERIC 0 2 008196 [SIM] Number of mean temperature values present NUMERIC 0 0 5 NUMERIC 0 2 008197 [SIM] Number of minimum temperature values present NUMERIC 0 0 5 NUMERIC 0 2 008198 [SIM] Number of maximum temperature values present NUMERIC 0 0 5 NUMERIC 0 2 008199 [SIM] Number of mean relative humidity values present NUMERIC 0 0 5 NUMERIC 0 2 008200 [SIM] Number of minimum relative humidity values present NUMERIC 0 0 5 NUMERIC 0 2 008201 [SIM] Number of maximum relative humidity values present NUMERIC 0 0 5 NUMERIC 0 2 008202 [SIM] Number of mean pressure values present NUMERIC 0 0 5 NUMERIC 0 2 008203 [SIM] Number of minimum pressure values present NUMERIC 0 0 5 NUMERIC 0 2 008204 [SIM] Number of maximum pressure values present NUMERIC 0 0 5 NUMERIC 0 2 008205 [SIM] Number of precipitation values present NUMERIC 0 0 5 NUMERIC 0 2 008206 [SIM] Number of leaf wetness values present NUMERIC 0 0 5 NUMERIC 0 2 008207 [SIM] Number of scalar wind velocity mean values present NUMERIC 0 0 5 NUMERIC 0 2 008208 [SIM] Number of cloud cover mean values present NUMERIC 0 0 5 NUMERIC 0 2 008209 [SIM] Number of cloud cover maximum values present NUMERIC 0 0 5 NUMERIC 0 2 008210 [SIM] Number of cloud cover minimum values present NUMERIC 0 0 5 NUMERIC 0 2 010004 PRESSURE PA -1 0 14 PA -1 5 010007 HEIGHT M 0 -1000 17 M 0 6 010008 GEOPOTENTIAL M**2/S**2 0 -10000 20 M**2/S**2 0 7 010009 GEOPOTENTIAL HEIGHT GPM 0 -1000 17 GPM 0 5 010051 PRESSURE REDUCED TO MEAN SEA LEVEL PA -1 0 14 PA -1 5 010052 ALTIMETER SETTING (QNH) PA -1 0 14 PA -1 5 010060 PRESSURE CHANGE PA -1 -1024 11 PA -1 4 010063 CHARACTERISTIC OF PRESSURE TENDENCY CODE TABLE 10063 0 0 4 CODE TABLE 10063 0 2 010197 ANEMOMETER HEIGHT M 0 0 9 M 0 3 011001 WIND DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011002 WIND SPEED M/S 1 0 12 M/S 1 4 011003 U-COMPONENT M/S 1 -4096 13 M/S 1 4 011004 V-COMPONENT M/S 1 -4096 13 M/S 1 4 011005 W-COMPONENT PA/S 1 -512 10 PA/S 1 4 011006 W-COMPONENT M/S 2 -4096 13 M/S 2 4 011016 EXTREME COUNTERCLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011017 EXTREME CLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011031 DEGREE OF TURBULENCE CODE TABLE 11031 0 0 4 CODE TABLE 11031 0 2 011036 MAXIMUM DERIVED EQUIVALENT VERTICAL GUST SPEED M/S 1 0 10 M/S 1 4 011037 TURBULENCE INDEX CODE TABLE 11037 0 0 6 CODE TABLE 11037 0 2 011039 EXTENDED TIME OF OCCURRENCE OF PEAK EDDY DISSIPATION RATE CODE TABLE 11039 0 0 6 CODE TABLE 11039 0 2 011041 MAXIMUM WIND GUST SPEED M/S 1 0 12 M/S 1 4 011043 MAXIMUM WIND GUST DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011050 STANDARD DEVIATION OF HORIZONTAL WIND SPEED M/S 1 0 12 M/S 1 4 011061 ABSOLUTE WIND SHEAR IN 1 KM LAYER BELOW M/S 1 0 12 M/S 1 4 011062 ABSOLUTE WIND SHEAR IN 1 KM LAYER ABOVE M/S 1 0 12 M/S 1 4 011075 MEAN TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 M**(2/3)/S 2 3 011076 PEAK TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 M**(2/3)/S 2 3 011077 REPORTING INTERVAL OR AVERAGING TIME FOR EDDY DISSIPATION RATE S 0 0 12 S 0 4 011192 [SIM] W-component terrain following M/S 2 -4096 13 M/S 2 4 011193 [SIM] Stability class NUMERIC 0 0 4 NUMERIC 0 2 011194 [SIM] Friction velocity (calmet) M/S 3 0 14 M/S 3 4 011195 [SIM] Mixing height (calmet) M 0 0 12 M 0 4 011196 [SIM] Obukov lenght (calmet) M 1 -100000 15 M 1 5 011197 [SIM] Convective velocitiy scale (calmet) M/S 3 0 14 M/S 3 4 011198 [SIM] SQRT(2*TKE) M/S 4 0 20 M/S 4 6 011199 [SIM] Surface Roughness M 3 0 14 M 1 4 011200 [SIM] U-component of momentum flux N/M**2 4 -524288 20 N/M**2 4 6 011201 [SIM] V-component of momentum flux N/M**2 4 -524288 20 N/M**2 4 6 011202 [SIM] Friction velocity (diagmet) M/S 3 0 14 M/S 3 4 011203 [SIM] Mixing height (diagmet) M 0 0 12 M 0 4 011204 [SIM] Obukov lenght (diagmet) M 1 -100000 15 M 1 5 011205 [SIM] Convective velocitiy scale (diagmet) M/S 3 0 14 M/S 3 4 011206 [SIM] Friction velocity (COSMO) M/S 3 0 14 M/S 3 4 011207 [SIM] Obukov lenght (COSMO) M 1 -100000 15 M 1 5 011208 [SIM] Distance covered by the hourly mean wind M 0 0 23 M 0 7 012001 TEMPERATURE/AIR TEMPERATURE K 1 0 12 C 1 3 012003 DEW-POINT TEMPERATURE K 1 0 12 C 1 3 012030 SOIL TEMPERATURE K 1 0 12 C 1 3 012049 Temperature change over specified period K 0 -30 6 C 0 2 012061 SKIN TEMPERATURE K 1 0 12 K 1 4 012063 BRIGHTNESS TEMPERATURE K 1 0 12 K 1 4 012101 TEMPERATURE/DRY-BULB TEMPERATURE K 2 0 16 K 2 5 012102 WET-BULB TEMPERATURE K 2 0 16 C 2 4 012103 DEW-POINT TEMPERATURE K 2 0 16 K 2 5 012121 GROUND MINIMUM TEMPERATURE K 2 0 16 C 2 4 012131 SNOW TEMPERATURE K 2 0 16 C 2 4 012192 POTENTIAL TEMPERATURE K 2 0 16 K 2 5 012193 PSEUDO-EQUIVALENT POTENTIAL TEMPERATURE K 2 0 16 K 2 5 012194 [SIM] Air density KG/M**3 6 0 20 KG/M**3 6 6 013001 SPECIFIC HUMIDITY KG/KG 5 0 14 KG/KG 5 5 013002 MIXING RATIO KG/KG 5 0 14 KG/KG 5 5 013003 RELATIVE HUMIDITY % 0 0 7 % 0 3 013011 TOTAL PRECIPITATION / TOTAL WATER EQUIVALENT KG/M**2 1 -1 14 KG/M**2 1 5 013012 DEPTH OF FRESH SNOW M 2 -2 12 M 2 4 013013 TOTAL SNOW DEPTH M 3 -20 20 M 3 6 013031 EVAPOTRANSPIRATION KG/M**2 1 0 7 KG/M**2 0 3 013033 EVAPORATION/EVAPOTRANSPIRATION KG/M**2 1 0 10 KG/M**2 1 4 013081 WATER CONDUCTIVITY S/M 3 0 14 S/M 3 4 013082 WATER TEMPERATURE K 1 0 12 K 1 4 013192 [SIM] Cloud liquid water content KG/KG 8 0 27 KG/KG 8 8 013193 [SIM] Cloud ice content KG/KG 8 0 27 KG/KG 8 8 013194 [SIM] Water table depth M 3 0 18 M 3 6 013195 [SIM] Precipitating liquid water KG/KG 8 0 27 KG/KG 8 8 013196 [SIM] Precipitating ice KG/KG 8 0 27 KG/KG 8 8 013197 [SIM] Total precipitating water+ice KG/KG 8 0 27 KG/KG 8 8 013198 [SIM] Total liquid water (cloud+precipitating) KG/KG 8 0 27 KG/KG 8 8 013199 [SIM] Total ice (cloud+precipitating) KG/KG 8 0 27 KG/KG 8 8 013200 [SIM] Grid-scale liquid precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013201 [SIM] Grid-scale snowfall KG/M**2 1 -1 14 KG/M**2 1 5 013202 [SIM] Convective liquid precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013203 [SIM] Convective snowfall KG/M**2 1 -1 14 KG/M**2 1 5 013204 [SIM] Total convective precipitation (liquid + snow) KG/M**2 1 -1 14 KG/M**2 1 5 013205 [SIM] Snowfall (grid-scale + convective) KG/M**2 1 -1 14 KG/M**2 1 5 013206 [SIM] Soil water content KG/M**2 1 0 14 KG/M**2 1 5 013210 [SIM] Penetration of the probe in the snow M 2 0 9 M 2 3 013212 [SIM] Leaf wetness duration S -1 0 24 S -1 7 013215 [SIM] River level M 2 -100000 18 M 2 6 013216 [SIM] Hourly precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013217 [SIM] 5 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013218 [SIM] 10 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013219 [SIM] 15 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013220 [SIM] 20 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013221 [SIM] 30 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013222 [SIM] 180 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013223 [SIM] 360 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013224 [SIM] 720 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013225 [SIM] 1440 minutes precipitation KG/M**2 1 -1 14 KG/M**2 1 5 013226 [SIM] River discharge M**3/S 2 0 21 M**3/S 2 7 013227 [SIM] Soil volumetric water content % 1 0 10 % 1 4 013228 [SIM] Piezometric level M 3 0 18 M 3 6 013229 [SIM] Density of snow KG/M**3 1 0 14 KG/M**3 1 5 013230 [SIM] Convective Available Potential Energy (CAPE) J/KG 1 0 17 J/KG 1 5 014002 Long-wave radiation, integrated over period specified J M-2 -3 -65536 17 J M-2 -3 5 014004 Short-wave radiation, integrated over period specified J M-2 -3 -65536 17 J M-2 -3 5 014016 NET RADIATION J/M**2 -4 -16384 15 J/M**2 -4 5 014017 INSTANTANEOUS LONG-WAVE RADIATION (incoming) W/M**2 0 -2048 12 W/M**2 0 4 014018 INSTANTANEOUS SHORT-WAVE RADIATION (incoming) W/M**2 0 -2048 12 W/M**2 -3 4 014019 SURFACE ALBEDO % 0 0 7 % 0 3 014021 GLOBAL SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 J/M**2 -4 5 014028 Global solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 J M-2 -2 6 014029 Diffuse solar radiation (high accuracy), integrated over period J M-2 -2 0 20 J M-2 -2 6 014030 Direct solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 J M-2 -2 6 014031 TOTAL SUNSHINE MINUTE 0 0 11 MINUTE 0 4 014192 [SIM] Instantenous sensible heat flux W/m**2 0 -1024 11 W/M**2 0 4 014193 [SIM] Instantenous latent heat flux W/m**2 0 -1024 11 W/M**2 0 4 014194 [SIM] Instantenous direct solar radiation W/M**2 0 -2048 12 W/M**2 -3 4 014195 [SIM] Instantenous diffuse solar radiation W/M**2 0 -2048 12 W/M**2 -3 4 014196 [SIM] INSTANTANEOUS NET LONG-WAVE RADIATION W/M**2 0 -2048 12 W/M**2 0 4 014197 [SIM] INSTANTANEOUS NET SHORT-WAVE RADIATION W/M**2 0 -2048 12 W/M**2 -3 4 014198 [SIM] Visible radiation (downward) W/M**2 3 -50000 21 W/M**2 3 7 014199 [SIM] Visible radiation (upward) W/M**2 3 -50000 21 W/M**2 3 7 014200 [SIM] Infrared radiation (downward) W/M**2 3 0 20 W/M**2 3 7 014201 [SIM] Infrared radiation (upward) W/M**2 3 0 20 W/M**2 3 7 015192 [SIM] NO Concentration KG/M**3 10 0 20 KG/M**3 10 6 015193 [SIM] NO2 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015194 [SIM] O3 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015195 [SIM] PM10 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015196 [SIM] CO Concentration KG/M**3 10 0 20 KG/M**3 10 6 015197 [SIM] SO2 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015198 [SIM] PM2.5 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015199 [SIM] NOY Concentration KG/M**3 10 0 20 KG/M**3 10 6 015200 [SIM] HCNM Concentration KG/M**3 10 0 20 KG/M**3 10 6 015201 [SIM] ALDE Concentration KG/M**3 10 0 20 KG/M**3 10 6 015202 [SIM] PM5 Concentration (tot. aerosol < 5 ug) KG/M**3 10 0 20 KG/M**3 10 6 015203 [SIM] PM1 Concentration (tot. aerosol < 1.25 ug) KG/M**3 10 0 20 KG/M**3 10 6 015204 [SIM] PM06 Concentration (tot. aerosol < 0.6 ug) KG/M**3 10 0 20 KG/M**3 10 6 015205 [SIM] PM03 Concentration (tot. aerosol < 0.3 ug) KG/M**3 10 0 20 KG/M**3 10 6 015206 [SIM] PM015 Concentration (tot. aerosol < 0.15 ug) KG/M**3 10 0 20 KG/M**3 10 6 015207 [SIM] PM008 Concentration (tot. aerosol < 0.08 ug) KG/M**3 10 0 20 KG/M**3 10 6 015208 [SIM] Concentration of primary particulate matter in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015209 [SIM] Concentration of sulfate in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015210 [SIM] Concentration of nitrate in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015211 [SIM] Concentration of ammonium in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015212 [SIM] Concentration of black carbon in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015213 [SIM] Concentration of organic carbon in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015214 [SIM] Concentration of dust in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015215 [SIM] Concentration of anthrop. A1D in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015216 [SIM] Concentration of anthrop. BmP in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015217 [SIM] Concentration of biogenic A1D in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015218 [SIM] Concentration of biogenic BmP in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015219 [SIM] Concentration of water in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015220 [SIM] Concentration of sea salt in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015221 [SIM] Concentration of secondary organic aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015222 [SIM] Total concentration of primary aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015223 [SIM] Total concentration of secondary aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015224 [SIM] Uncertainity in O3 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015225 [SIM] Uncertainity in PM10 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015226 [SIM] Uncertainity in NO2 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015227 [SIM] Uncertainity in PM2.5 estimate (Pesco) KG/M**3 10 0 20 KG/M**3 10 6 015228 [SIM] NH3 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015229 [SIM] Concentration of primary part. matter in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015230 [SIM] Concentration of sulfate in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015231 [SIM] Concentration of nitrate in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015232 [SIM] Concentration of ammonium in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015233 [SIM] Concentration of anthrop. sec. org. in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015234 [SIM] Concentration of biogenic sec. org. in aerosol KG/M**3 10 0 20 KG/M**3 10 6 015235 [SIM] Concentration of ISOPA1 in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015236 [SIM] C6H6 Concentration KG/M**3 10 0 20 KG/M**3 10 6 015237 [SIM] Concentration of anthropogenic aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015238 [SIM] Concentration of biogenic aerosol in PM10 KG/M**3 10 0 20 KG/M**3 10 6 015239 [SIM] Concentration of anthropogenic aerosol in PM2.5 KG/M**3 10 0 20 KG/M**3 10 6 015240 [SIM] Concentration of biogenic aerosol in PM2.5 KG/M**3 10 0 20 KG/M**3 10 6 015241 [SIM] Aerosol Optical Thickness NUMERIC 4 0 15 NUMERIC 4 5 020001 HORIZONTAL VISIBILITY M -1 0 13 M -1 4 020003 PRESENT WEATHER (SEE NOTE 1) CODE TABLE 20003 0 0 9 CODE TABLE 20003 0 3 020004 PAST WEATHER (1) (SEE NOTE 2) CODE TABLE 20004 0 0 5 CODE TABLE 20004 0 2 020005 PAST WEATHER (2) (SEE NOTE 2) CODE TABLE 20005 0 0 5 CODE TABLE 20005 0 2 020009 GENERAL WEATHER INDICATOR (TAF/METAR) CODE TABLE 20009 0 0 4 CODE TABLE 20009 0 2 020010 CLOUD COVER (TOTAL) % 0 0 7 % 0 3 020011 CLOUD AMOUNT CODE TABLE 20011 0 0 4 CODE TABLE 20011 0 2 020012 CLOUD TYPE CODE TABLE 20012 0 0 6 CODE TABLE 20012 0 2 020013 HEIGHT OF BASE OF CLOUD M 0 -400 17 M 0 5 020017 CLOUD TOP DESCRIPTION CODE TABLE 20017 0 0 4 CODE TABLE 20017 0 2 020019 SIGNIFICANT PRESENT OR FORECAST WEATHER CCITTIA5 0 0 72 CHARACTER 0 9 020021 TYPE OF PRECIPITATION FLAG TABLE 20021 0 0 30 FLAG TABLE 20021 0 10 020031 ICE DEPOSIT (THICKNESS) M 2 0 7 M 2 3 020032 RATE OF ICE ACCRETION CODE TABLE 20032 0 0 3 CODE TABLE 20032 0 1 020033 CAUSE OF ICE ACCRETION FLAG TABLE 20033 0 0 4 FLAG TABLE 20033 0 2 020034 SEA ICE CONCENTRATION CODE TABLE 20034 0 0 5 CODE TABLE 20034 0 2 020035 AMOUNT AND TYPE OF ICE CODE TABLE 20035 0 0 4 CODE TABLE 20035 0 2 020036 ICE SITUATION CODE TABLE 20036 0 0 5 CODE TABLE 20036 0 2 020037 ICE DEVELOPMENT CODE TABLE 20037 0 0 5 CODE TABLE 20037 0 2 020038 BEARING OF ICE EDGE (SEE NOTE 3) DEGREE TRUE 0 0 12 DEGREE TRUE 0 3 020042 AIRFRAME ICING PRESENT CODE TABLE 20042 0 0 2 CODE TABLE 20042 0 1 020043 PEAK LIQUID WATER CONTENT KG/M**3 4 0 7 KG/M**3 4 2 020044 AVERAGE LIQUID WATER CONTENT KG/M**3 4 0 7 KG/M**3 4 2 020045 SUPERCOOLED LARGE DROPLET (SLD) CONDITIONS CODE TABLE 20045 0 0 2 CODE TABLE 20045 0 2 020062 STATE OF THE GROUND (WITH OR WITHOUT SNOW) CODE TABLE 20062 0 0 5 CODE TABLE 20062 0 2 020192 [SIM] Presence of rain > 1mm BOOLEAN 0 0 1 BOOLEAN 0 1 020193 [SIM] Cloud type (METAR) CCITTIA5 0 0 16 CHARACTER 0 2 020194 [SIM] Presence of shower BOOLEAN 0 0 1 BOOLEAN 0 1 020195 [SIM] Presence of hail BOOLEAN 0 0 1 BOOLEAN 0 1 020196 [SIM] Presence of thunderstorm BOOLEAN 0 0 1 BOOLEAN 0 1 020197 [SIM] Presence of snow BOOLEAN 0 0 1 BOOLEAN 0 1 020198 [SIM] Presence of frost BOOLEAN 0 0 1 BOOLEAN 0 1 020199 [SIM] Presence of dew BOOLEAN 0 0 1 BOOLEAN 0 1 020200 [SIM] Presence of fog BOOLEAN 0 0 1 BOOLEAN 0 1 020201 [SIM] Presence of water-spout BOOLEAN 0 0 1 BOOLEAN 0 1 020202 [SIM] State of the ground with snow CODE TABLE 0 0 5 CODE TABLE 0 2 022001 DIRECTION OF WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022002 DIRECTION OF WIND WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022003 DIRECTION OF SWELL WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022004 DIRECTION OF CURRENT DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022011 PERIOD OF WAVES S 0 0 6 S 0 2 022012 PERIOD OF WIND WAVES S 0 0 6 S 0 2 022013 PERIOD OF SWELL WAVES S 0 0 6 S 0 2 022021 HEIGHT OF WAVES M 1 0 10 M 1 4 022022 HEIGHT OF WIND WAVES M 1 0 10 M 1 4 022023 HEIGHT OF SWELL WAVES M 1 0 10 M 1 4 022031 SPEED OF CURRENT M/S 2 0 13 M/S 2 4 022032 SPEED OF SEA SURFACE CURRENT M/S 2 0 13 M/S 2 4 022037 Tidal elevation with respect to national land datum M 3 -10000 15 M 3 5 022038 Tidal elevation with respect to local chart datum M 3 -10000 15 M 3 5 022042 SEA/WATER TEMPERATURE K 1 0 12 K 1 4 022043 SEA/WATER TEMPERATURE K 2 0 15 K 2 5 022049 SEA-SURFACE TEMPERATURE K 2 0 15 K 2 5 022070 SIGNIFICANT WAVE HEIGHT M 2 0 13 M 2 4 022071 SPECTRAL PEAK WAVE PERIOD S 1 0 9 S 1 3 022074 AVERAGE WAVE PERIOD S 1 0 9 S 1 3 022192 [SIM] Current X component M/S 2 0 13 M/S 2 4 022193 [SIM] Current Y component M/S 2 0 13 M/S 2 4 023192 [SIM] Dry deposition of H2SO4 MOL/M**2 5 0 20 MOL/M**3 5 6 023193 [SIM] Wet deposition of H2SO4 MOL/M**2 5 0 20 MOL/M**3 5 6 023194 [SIM] Dry deposition of NH4 MOL/M**2 5 0 20 MOL/M**3 5 6 023195 [SIM] Wet deposition of NH4 MOL/M**2 5 0 20 MOL/M**3 5 6 023196 [SIM] Dry deposition of HNO3 MOL/M**2 5 0 20 MOL/M**3 5 6 023197 [SIM] Wet deposition of HNO3 MOL/M**2 5 0 20 MOL/M**3 5 6 023198 [SIM] Solid transport by river KG/S 2 0 24 KG/S 2 8 025076 LOG-10 OF (TEMP-RAD CENTRAL WAVENUMBER) FOR ATOVS LOGM-1 8 0 30 LOGM-1 8 10 029192 [SIM] Land fraction % 1 0 10 % 1 4 031000 SHORT DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 1 NUMERIC 0 1 031001 DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031011 DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031012 EXTENDED DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031021 ASSOCIATED FIELD SIGNIFICANCE CODE TABLE 31021 0 0 6 CODE TABLE 31021 0 2 031031 DATA PRESENT INDICATOR FLAG TABLE 31031 0 0 1 FLAG TABLE 31031 0 1 033002 QUALITY INFORMATION CODE TABLE 33002 0 0 2 CODE TABLE 33002 0 1 033003 QUALITY INFORMATION CODE TABLE 33003 0 0 3 CODE TABLE 33003 0 1 033005 QUALITY INFORMATION (AWS DATA) FLAG TABLE 33005 0 0 30 FLAG TABLE 33005 0 10 033006 INTERNAL MEASUREMENT STATUS INFORMATION (AWS) CODE TABLE 33006 0 0 3 CODE TABLE 33006 0 1 033007 PER CENT CONFIDENCE % 0 0 7 % 0 3 033015 DATA QUALITY CHECK INDICATOR CODE TABLE 33015 0 0 6 CODE TABLE 33015 0 2 033020 QUALITY CONTROL INDICATION OF FOLLOWING VALUE CODE TABLE 33020 0 0 3 CODE TABLE 33020 0 1 033021 QUALITY OF FOLLOWING VALUE CODE TABLE 33021 0 0 2 CODE TABLE 33021 0 1 033022 QUALITY OF BUOY SATELLITE TRANSMISSION CODE TABLE 33022 0 0 2 CODE TABLE 33022 0 1 033023 QUALITY OF BUOY LOCATION CODE TABLE 33023 0 0 2 CODE TABLE 33023 0 1 033024 STATION ELEVATION QUALITY MARK (FOR MOBILE STATIONS) CODE TABLE 33024 0 0 4 CODE TABLE 33024 0 2 033025 ACARS INTERPOLATED VALUES CODE TABLE 33025 0 0 3 CODE TABLE 33025 0 1 033026 MOISTURE QUALITY CODE TABLE 33026 0 0 6 CODE TABLE 33026 0 2 033027 LOCATION QUALITY CLASS (RANGE OF RADIUS OF 66 % CONFIDENCE) CODE TABLE 33027 0 0 3 CODE TABLE 33027 0 1 033030 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 33030 0 0 24 FLAG TABLE 33030 0 8 033031 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 33031 0 0 24 FLAG TABLE 33031 0 8 033032 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 33032 0 0 24 FLAG TABLE 33032 0 8 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS FLAG TABLE 33033 0 0 24 FLAG TABLE 33033 0 8 033035 MANUAL/AUTOMATIC QUALITY CONTROL CODE TABLE 33035 0 0 4 CODE TABLE 33035 0 2 033036 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 % 0 3 033037 WIND CORRELATION ERROR FLAG TABLE 33037 0 0 20 FLAG TABLE 33037 0 7 033038 QUALITY FLAGS FOR GROUND-BASED GNSS DATA FLAG TABLE 33038 0 0 10 FLAG TABLE 33038 0 4 033040 CONFIDENCE INTERVAL % 0 0 7 PERCENT 0 3 033041 ATTRIBUTE OF FOLLOWING VALUE CODE TABLE 33041 0 0 2 CODE TABLE 33041 0 1 033050 GLOBAL GTSPP QUALITY FLAG CODE TABLE 33050 0 0 4 CODE TABLE 33050 0 2 033192 [SIM] Climatological and consistency check % 0 0 7 PERCENT 0 3 033193 [SIM] Time consistency % 0 0 7 PERCENT 0 3 033194 [SIM] Space consistency % 0 0 7 PERCENT 0 3 033195 [SIM] MeteoDB variable ID NUMERIC 0 0 24 NUMERIC 0 8 033196 [SIM] Data has been invalidated CODE TABLE 33196 0 0 2 CODE TABLE 33196 0 1 033197 [SIM] Manual replacement in substitution CODE TABLE 33197 0 0 2 CODE TABLE 33197 0 1 033198 [SIM] Observation increment NUMERIC 4 -1073741823 31 NUMERIC 4 10 033201 [SIM] Kalman coefficient, state vector (s.v.) x1 NUMERIC 4 -1073741823 31 NUMERIC 4 10 033202 [SIM] Kalman coefficient, state vector (s.v.) x2 NUMERIC 4 -1073741823 31 NUMERIC 4 10 033203 [SIM] Kalman coefficient, s.v. error covariance matrix(1,1) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033204 [SIM] Kalman coefficient, s.v. error covariance matrix(1,2) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033205 [SIM] Kalman coefficient, s.v. error covariance matrix(2,1) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033206 [SIM] Kalman coefficient, s.v. error covariance matrix(2,2) NUMERIC 4 -1073741823 31 NUMERIC 4 10 033207 [SIM] Kalman observation sequential counter NUMERIC 0 -127 8 NUMERIC 0 3 033208 [SIM] Kalman osservation missing counter NUMERIC 0 -127 8 NUMERIC 0 3 033209 [SIM] Normalized Density Index % 0 0 7 PERCENT 0 3 048001 [SIM] Graminacee_Graminacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048002 [SIM] Betulacee_Ontano nero POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048003 [SIM] Betulacee_Betulla POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048004 [SIM] Betulacee_Betulacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048005 [SIM] Composite_Ambrosia POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048006 [SIM] Composite_Artemisia POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048007 [SIM] Composite_Composite indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048008 [SIM] Corilacee_Nocciolo POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048009 [SIM] Corilacee_Carpino bianco -Carpino nero POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048010 [SIM] Corilacee_Corilacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048011 [SIM] Fagacee_Castagno POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048012 [SIM] Fagacee_Faggio POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048013 [SIM] Fagacee_Quercia POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048014 [SIM] Fagacee_Fagacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048015 [SIM] Oleacee_Olivo POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048016 [SIM] Oleacee_Frassino POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048017 [SIM] Oleacee_Oleacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048018 [SIM] Plantaginacee_Plantaginacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048019 [SIM] Urticacee_Urticacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048020 [SIM] Cupressacee - Taxacee indistinte_Cipresso comune POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048021 [SIM] Cupressacee - Taxacee indistinte_Cupressacee - Taxacee ind POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048022 [SIM] Chenopodiacee - Amarantacee Indistinte_Amaranto POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048023 [SIM] Chenopodiacee - Amarantacee Indistinte_Chenopodiacee - Ama POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048024 [SIM] Poligonacee_Poligonacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048025 [SIM] Euphorbiacee_Euforbiacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048026 [SIM] Mirtacee_Mirtacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048027 [SIM] Ulmacee_Bagolaro comune POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048028 [SIM] Ulmacee_Olmo campestre POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048029 [SIM] Ulmacee_Ulmacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048030 [SIM] Platanacee_Platanacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048031 [SIM] Aceraceae_Aceracee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048032 [SIM] Pinacee_Pinacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048033 [SIM] Salicacee_Salice comune POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048034 [SIM] Salicacee_Pioppo POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048035 [SIM] Salicacee_Salicacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048036 [SIM] Ciperacee_Ciperacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048037 [SIM] Juglandacee_Juglandacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048038 [SIM] Ippocastanacee_Ippocastanacee indistinte POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048039 [SIM] Spore fungine_Alternaria POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048040 [SIM] Spore fungine_Botrytis POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048041 [SIM] Spore fungine_Stemphylium POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048042 [SIM] Spore fungine_Cladosporium POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048043 [SIM] Spore fungine_Epicoccum POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048044 [SIM] Altri Pollini / Non Identificati_Altri pollini identificat POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048045 [SIM] Altri Pollini / Non Identificati_Pollini non identificati POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048046 [SIM] Altre Spore / Non identificati_Altre spore fungine POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048047 [SIM] Altre Spore / Non identificati_Spore fungine non identific POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048048 [SIM] Graminacee_Graminacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048049 [SIM] Plantaginacee_Plantaginacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048050 [SIM] Urticacee_Urticacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048051 [SIM] Poligonacee_Poligonacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048052 [SIM] Euphorbiacee_Euforbiacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048053 [SIM] Mirtacee_Mirtacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048054 [SIM] Platanacee_Platanacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048055 [SIM] Aceraceae_Aceracee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048056 [SIM] Pinacee_Pinacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048057 [SIM] Ciperacee_Ciperacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048058 [SIM] Juglandacee_Juglandacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048059 [SIM] Ippocastanacee_Ippocastanacee indistinte 1 POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048060 [SIM] Oleacee_Ligustro POLLEN/M**3 1 0 24 POLLEN/M**3 1 8 048128 [SIM] Conta Graminacee_Graminacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048129 [SIM] Conta Betulacee_Ontano nero NUMERIC 0 0 20 NUMERIC 0 7 048130 [SIM] Conta Betulacee_Betulla NUMERIC 0 0 20 NUMERIC 0 7 048131 [SIM] Conta Betulacee_Betulacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048132 [SIM] Conta Composite_Ambrosia NUMERIC 0 0 20 NUMERIC 0 7 048133 [SIM] Conta Composite_Artemisia NUMERIC 0 0 20 NUMERIC 0 7 048134 [SIM] Conta Composite_Composite indistinte NUMERIC 0 0 20 NUMERIC 0 7 048135 [SIM] Conta Corilacee_Nocciolo NUMERIC 0 0 20 NUMERIC 0 7 048136 [SIM] Conta Corilacee_Carpino bianco -Carpino nero NUMERIC 0 0 20 NUMERIC 0 7 048137 [SIM] Conta Corilacee_Corilacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048138 [SIM] Conta Fagacee_Castagno NUMERIC 0 0 20 NUMERIC 0 7 048139 [SIM] Conta Fagacee_Faggio NUMERIC 0 0 20 NUMERIC 0 7 048140 [SIM] Conta Fagacee_Quercia NUMERIC 0 0 20 NUMERIC 0 7 048141 [SIM] Conta Fagacee_Fagacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048142 [SIM] Conta Oleacee_Olivo NUMERIC 0 0 20 NUMERIC 0 7 048143 [SIM] Conta Oleacee_Frassino NUMERIC 0 0 20 NUMERIC 0 7 048144 [SIM] Conta Oleacee_Oleacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048145 [SIM] Conta Plantaginacee_Plantaginacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048146 [SIM] Conta Urticacee_Urticacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048147 [SIM] Conta Cupressacee - Taxacee indistinte_Cipresso comune NUMERIC 0 0 20 NUMERIC 0 7 048148 [SIM] Conta Cupressacee - Taxacee indistinte_Cupressacee - Taxac NUMERIC 0 0 20 NUMERIC 0 7 048149 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Amaranto NUMERIC 0 0 20 NUMERIC 0 7 048150 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Chenopodiacee NUMERIC 0 0 20 NUMERIC 0 7 048151 [SIM] Conta Poligonacee_Poligonacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048152 [SIM] Conta Euphorbiacee_Euforbiacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048153 [SIM] Conta Mirtacee_Mirtacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048154 [SIM] Conta Ulmacee_Bagolaro comune NUMERIC 0 0 20 NUMERIC 0 7 048155 [SIM] Conta Ulmacee_Olmo campestre NUMERIC 0 0 20 NUMERIC 0 7 048156 [SIM] Conta Ulmacee_Ulmacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048157 [SIM] Conta Platanacee_Platanacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048158 [SIM] Conta Aceraceae_Aceracee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048159 [SIM] Conta Pinacee_Pinacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048160 [SIM] Conta Salicacee_Salice comune NUMERIC 0 0 20 NUMERIC 0 7 048161 [SIM] Conta Salicacee_Pioppo NUMERIC 0 0 20 NUMERIC 0 7 048162 [SIM] Conta Salicacee_Salicacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048163 [SIM] Conta Ciperacee_Ciperacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048164 [SIM] Conta Juglandacee_Juglandacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048165 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte NUMERIC 0 0 20 NUMERIC 0 7 048166 [SIM] Conta Spore fungine_Alternaria NUMERIC 0 0 20 NUMERIC 0 7 048167 [SIM] Conta Spore fungine_Botrytis NUMERIC 0 0 20 NUMERIC 0 7 048168 [SIM] Conta Spore fungine_Stemphylium NUMERIC 0 0 20 NUMERIC 0 7 048169 [SIM] Conta Spore fungine_Cladosporium NUMERIC 0 0 20 NUMERIC 0 7 048170 [SIM] Conta Spore fungine_Epicoccum NUMERIC 0 0 20 NUMERIC 0 7 048171 [SIM] Conta Altri Pollini / Non Identificati_Altri pollini ident NUMERIC 0 0 20 NUMERIC 0 7 048172 [SIM] Conta Altri Pollini / Non Identificati_Pollini non identif NUMERIC 0 0 20 NUMERIC 0 7 048173 [SIM] Conta Altre Spore / Non identificati_Altre spore fungine NUMERIC 0 0 20 NUMERIC 0 7 048174 [SIM] Conta Altre Spore / Non identificati_Spore fungine non ide NUMERIC 0 0 20 NUMERIC 0 7 048175 [SIM] Conta Graminacee_Graminacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048176 [SIM] Conta Plantaginacee_Plantaginacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048177 [SIM] Conta Urticacee_Urticacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048178 [SIM] Conta Poligonacee_Poligonacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048179 [SIM] Conta Euphorbiacee_Euforbiacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048180 [SIM] Conta Mirtacee_Mirtacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048181 [SIM] Conta Platanacee_Platanacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048182 [SIM] Conta Aceraceae_Aceracee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048183 [SIM] Conta Pinacee_Pinacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048184 [SIM] Conta Ciperacee_Ciperacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048185 [SIM] Conta Juglandacee_Juglandacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048186 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte 1 NUMERIC 0 0 20 NUMERIC 0 7 048187 [SIM] Conta Oleacee_Ligustro NUMERIC 0 0 20 NUMERIC 0 7 dballe-7.7/tables/D000299.txt0000644000175000017500000052523112652630043012426 00000000000000 D00002 2 B00002 B00003 D00003 3 B00010 B00011 B00012 D00004 9 D00003 B00013 B00014 B00015 B00016 B00017 B00018 B00019 B00020 D00010 3 D00003 R01000 B00030 D01001 2 B01001 B01002 D01002 3 B01003 B01004 B01005 D01003 3 B01011 B01012 B01013 D01004 4 B01001 B01002 B01015 B02001 D01011 3 B04001 B04002 B04003 D01012 2 B04004 B04005 D01013 3 B04004 B04005 B04006 D01021 2 B05001 B06001 D01022 3 B05001 B06001 B07001 D01023 2 B05002 B06002 D01024 3 B05002 B06002 B07001 D01025 3 D01023 B04003 D01012 D01026 7 D01021 B04003 B04003 B04004 B04004 B04005 B04005 D01029 3 B01018 B02001 D01011 D01030 4 B01018 B02001 D01011 D01024 D01031 5 D01001 B02001 D01011 D01012 D01022 D01032 5 D01001 B02001 D01011 D01012 D01024 D01033 5 B01005 B02001 D01011 D01012 D01021 D01034 5 B01005 B02001 D01011 D01012 D01023 D01035 7 B01005 B01012 B01013 B02001 D01011 D01012 D01023 D01036 5 D01003 B02001 D01011 D01012 D01023 D01037 6 D01001 B02011 B02012 D01011 D01012 D01022 D01038 6 D01001 B02011 B02012 D01011 D01012 D01024 D01039 6 D01003 B02011 B02012 D01011 D01012 D01023 D01040 6 D01003 B02011 B02012 D01011 D01012 D01024 D01041 5 B01007 B02021 B02022 D01011 D01012 D01042 2 D01041 D01021 D01043 5 B01007 B02023 D01011 D01013 D01021 D01044 5 B01007 B02024 D01011 D01013 D01021 D01049 5 B02111 B02112 B21062 B21063 B21065 D01051 6 B01006 B02061 D01011 D01012 D01021 B08004 D01055 7 B01005 B02001 D01011 D01012 D01021 B01012 B01014 D01062 2 R01000 D01001 D01065 8 B01006 B01008 B02001 B02002 B02005 B02062 B02070 B02065 D01066 6 D01011 D01013 D01023 B07004 B02064 B08004 D01070 3 B02143 B02142 B02144 D01071 5 B01007 B01031 B02020 B02028 B02029 D01072 4 D01071 D01011 D01013 D01021 D01074 4 B02143 B02142 B02145 B02146 D01075 6 D01001 B01015 D01024 B08021 D01011 D01012 D01076 3 B02011 B02143 B02142 D01090 6 D01004 D01011 D01012 D01021 B07030 B07031 D01091 10 B02180 B02181 B02182 B02183 B02184 B02179 B02186 B02187 B02188 B02189 D01193 5 001007 001031 002196 002221 002222 D01250 4 D01193 D01011 D01013 D01021 D02001 4 B10004 B10051 B10061 B10063 D02002 5 B10004 B07004 B10003 B10061 B10063 D02003 9 B11011 B11012 B12004 B12006 B13003 B20001 B20003 B20004 B20005 D02004 7 B20010 B08002 B20011 B20013 B20012 B20012 B20012 D02005 4 B08002 B20011 B20012 B20013 D02006 4 B10004 B10051 B10062 B10063 D02011 3 D02001 D02003 D02004 D02012 3 D02002 D02003 D02004 D02013 4 D02006 D02003 R01000 D02005 D02021 3 B22001 B22011 B22021 D02022 3 B22002 B22012 B22022 D02023 3 B22003 B22013 B22023 D02024 3 D02022 R01002 D02023 D02051 12 B10004 B10051 B07004 B10003 B12004 B12051 B12016 B12017 B13004 R02004 B08051 B08020 D02069 4 B07032 B07033 B33041 B20001 D02070 8 B07032 B07033 B11001 B11002 B11043 B11041 B11016 B11017 D02071 14 B07032 B07033 B08021 B04025 B11001 B11002 B08021 R03002 B04025 B11043 B11041 B04025 B11016 B11017 D02072 5 B07032 B07033 B12101 B12103 B13003 D02073 7 B20010 R05004 B08002 B20011 B20012 B33041 B20013 D02074 4 B20003 B04025 B20004 B20005 D02075 5 B08021 B04025 B13055 B13058 B08021 D02076 7 B02021 B20022 B26020 B20023 B20024 B20025 B20026 D02077 12 B07032 B07033 B04025 B12111 B12112 B07032 B04025 B12112 B02176 B20062 B02177 B13013 D02078 4 B02176 B20062 B02177 B13013 D02079 5 B07032 B02175 B02178 B04025 B13011 D02080 3 B02185 B04025 B13033 D02081 2 B04025 B14031 D02082 7 B04025 B14002 B14004 B14016 B14028 B14029 B14030 D02083 8 B04025 B08023 B10004 B11001 B11002 B12101 B13003 B08023 D03001 3 B07003 B11001 B11002 D03002 3 B07004 B11001 B11002 D03003 4 B07004 B10003 B12001 B12003 D03004 6 B07004 B10003 B12001 B12003 B11001 B11002 D03011 4 B07003 B08001 B11001 B11002 D03012 4 B07004 B08001 B11001 B11002 D03013 7 B07004 B08001 B10003 B12001 B13003 B11001 B11002 D03014 7 B07004 B08001 B10003 B12001 B12003 B11001 B11002 D03031 6 B07004 B08003 B07021 B07022 B08012 B12061 D03032 2 B20011 B20016 D03033 2 B20010 B20016 D03041 8 B02152 B02023 B07004 B11001 B11002 B02153 B02154 B12071 D03250 8 B02252 B02023 B07004 B11001 B11002 B02197 B02198 B12193 D04001 5 B08003 B10004 B12001 B11001 B11002 D04002 4 B08003 B10004 B11001 B11002 D04003 2 B08003 B12001 D04004 4 B08003 B10004 B20010 B12001 D04005 4 B02024 B07004 B07004 B13003 D04006 3 B14001 B14001 B14003 D04011 27 B02163 B02164 B08012 B07024 B02057 B08021 B04001 B04002 B04003 B04004 B08021 B04024 R10004 B08021 B04004 B04005 B04006 B08021 B04004 B04005 B04006 B11001 B11002 R03010 B02163 B07004 B12001 D04030 3 B27031 B28031 B10031 D04031 3 B01041 B01042 B01043 D04032 5 B02153 B02154 B20081 B20082 B20012 D04033 8 B02152 B02166 B02167 B02153 B02154 B12075 B12076 B12063 D04034 9 R02004 B27001 B28001 B07022 B05043 B20010 B20016 B33003 B10040 D04250 27 B02231 B02232 B08012 B07024 B02057 B08021 B04001 B04002 B04003 B04004 B08021 B04024 R10004 B08021 B04004 B04005 B04006 B08021 B04004 B04005 B04006 B11001 B11002 R03010 B02231 B07004 B12001 D05001 4 B11001 B11002 B13060 B13071 D05002 11 D01012 B12001 B13003 B14051 B13060 B13072 B13080 B13081 B13082 B13083 B13084 D05003 4 D01012 B04065 R01000 D05001 D05004 3 D01030 D05002 D05003 D05006 8 B13072 B13082 B13019 C07005 C01004 B12001 B13073 B13060 D05007 5 D01029 D01012 B04065 R01000 D05006 D05008 4 D05006 C07005 C01004 B12030 D05009 5 D01029 D01012 B04065 R01000 D05008 D05010 3 D05008 B02091 B02091 D05011 5 D01029 D01012 B04065 R01000 D05010 D05016 7 B14021 B07004 B13003 B11002 B11001 B11041 B11043 D05017 5 B13080 B13081 B13083 B13085 B13084 D05018 7 D01029 D01012 B04065 R03000 D05008 D05016 D05017 D06001 4 B02032 R02000 B07062 B22042 D06002 3 B02031 B22004 B22031 D06003 4 B02002 B11011 B11012 B12004 D06004 6 B02032 B02033 R03000 B07062 B22043 B22062 D06005 5 B02031 R03000 B07062 B22004 B22031 D06006 3 D06003 D06002 B22063 D06007 6 B01012 B01014 D06008 B04024 B27003 B28003 D06008 3 B02034 B02035 B02036 D06020 8 B01075 D01011 D01012 B22042 B22120 B22121 B04075 B04065 D06021 7 B01075 D01011 D01012 B22122 B22123 B12001 D03002 D06022 5 B01075 D01011 D01012 B22038 B22039 D06023 8 B01015 D01023 D01011 D01012 B22038 B22039 B22120 B22121 D06024 4 D06020 R02000 B22038 B22039 D07001 2 D01031 D02011 D07002 2 D01032 D02011 D07003 3 D07001 R01000 D02005 D07004 3 D07002 R01000 D02005 D07005 3 D07001 R01004 D02005 D07006 3 D07002 R01004 D02005 D07007 2 D01031 D02012 D07008 2 D01032 D02012 D07009 2 D01031 D02013 D07011 16 B01063 B02001 D01011 D01012 D01024 B07006 B11001 B11016 B11017 B11002 B11041 B07006 B12001 B12003 B10052 B20009 D07012 4 R03000 B08023 B05021 B20001 D07013 7 R06000 B01064 B08014 B20061 B08014 B20061 B20018 D07014 2 R01000 B20019 D07015 3 R01000 D02005 B20002 D07016 2 R01000 B20020 D07017 2 R01000 B11070 D07018 13 B08016 R02000 B08017 D01012 R04000 B07006 B11001 B11002 B11041 B20009 R01000 B20001 D07014 D07020 3 D07011 D07014 D07016 D07021 9 D07011 D07012 D07013 D07014 D07015 D07016 D07017 D07018 D07015 D07030 2 B15001 B15002 D07031 7 B08022 B08023 B15001 B08023 B15001 B08023 B15002 D07041 7 D01001 B01015 D01024 D01011 D01012 D01070 D07030 D07042 9 D01001 B01015 D01024 D01011 D01012 B08021 B04025 D01070 D07031 D07043 7 D01001 B01015 D01024 D01011 D01012 D01074 D07030 D07044 9 D01001 B01015 D01024 D01011 D01012 B08021 B04025 D01074 D07031 D07060 2 B07061 B12030 D07061 3 D01031 R01005 D07060 D07062 3 D01032 R01005 D07060 D07063 2 B07061 B12130 D08001 3 D01033 D02011 B22042 D08002 3 D01034 D02011 B22042 D08003 3 D01035 D02011 B22042 D08004 3 D01036 D02011 B22042 D08005 2 D08004 D02024 D08006 8 B10004 B10061 B10063 B11001 B11002 B12004 B13003 B22042 D08007 4 D01055 D02011 B07062 B22042 D09001 3 D01037 R01000 D03011 D09002 3 D01038 R01000 D03011 D09003 3 D01037 R01000 D03012 D09004 3 D01038 R01000 D03012 D09005 4 D01037 D02004 R01000 D03013 D09006 4 D01038 D02004 R01000 D03013 D09007 4 D01037 D02004 R01000 D03014 D09008 4 D01038 D02004 R01000 D03014 D09011 3 D01039 R01000 D03011 D09012 3 D01039 R01000 D03012 D09013 4 D01039 D02004 R01000 D03013 D09014 4 D01039 D02004 R01000 D03014 D09015 3 D01040 R01000 D03011 D09016 3 D01040 R01000 D03012 D09017 4 D01040 D02004 R01000 D03013 D09018 4 D01040 D02004 R01000 D03014 D09019 4 D01031 B02003 R01000 D03011 D09020 7 D01031 B02003 R04000 B07003 B11003 B11004 B11005 D09030 7 B15004 B15005 R04000 B04015 B08006 B07004 B15003 D09040 3 D01075 D01076 D09030 D09041 4 D07041 D01075 D01076 D09030 D09042 4 D07042 D01075 D01076 D09030 D09044 4 D07044 D01075 D01076 D09030 D10001 5 D01042 D03031 D03032 R01026 D03025 D10002 5 D01042 D03031 D03032 R01009 D03023 D10003 5 D01042 D03031 D03032 R01006 D03023 D10004 5 D01042 D03031 D03032 R01003 D03024 D10005 5 D01042 D03031 D03033 R01000 D03025 D10006 5 D01042 D03031 D03033 R01000 D03023 D10007 5 D01042 D03031 D03033 R01000 D03024 D10008 8 D10011 R01019 D10012 B02150 B25079 B25080 B33032 B14045 D10009 3 D10011 R01015 D10012 D10010 3 D10011 R01005 D10012 D10014 3 D01072 D03041 D04011 D10015 13 D01072 B07024 B10002 D03041 R01003 D04032 B02152 B02024 B07004 B07004 B13003 R01003 D04033 D10016 13 D01072 B07024 B10002 D03041 R01012 D04032 B02152 B02024 B07004 B07004 B13003 R01012 D04033 D10020 6 D10022 D01011 D01013 D01021 D04034 D10021 D10022 4 B01007 B02019 B01033 B02172 D10023 17 D01072 B30021 B30022 B08012 B07024 B07025 B10002 R01012 D04032 R05002 B02152 B02024 B07004 B07004 B13003 R01012 D04033 D10050 13 D10051 D10052 R01000 D10053 R01004 D10054 B20010 D10052 R01015 D10053 D10052 R01004 D10053 D10195 3 D01250 D03250 D04250 D11001 9 D01051 B07002 B12001 B11001 B11002 B11031 B11032 B11033 B20041 D11002 4 D01065 D01066 D11003 D11004 D11003 5 B10070 B11001 B11002 B12001 B13002 D11004 12 R01000 B11034 R01000 B11035 R01000 B11075 R01000 B11076 R01000 B33025 R01000 B33026 D11005 13 B01008 B01023 D01021 D01011 D01013 B07010 B08009 B11001 B11002 B11031 B11036 B12101 B33025 D11006 6 B07010 B11001 B11002 B02064 B12101 B12103 D11193 16 D01197 D01011 D01012 D01023 B08004 B07004 B08021 B11001 B11002 B11031 B11034 B11035 B12001 B12003 B13003 B20041 D12001 2 D01043 D04001 D12002 2 D01043 D04002 D12003 2 D01042 D04003 D12004 2 D01042 D04004 D12005 2 D01042 B20014 D12006 2 D01044 D04005 D12007 2 D01042 D04006 D12010 6 B01007 B05040 B02021 B05041 B04001 B04043 D12014 8 D12010 D12011 R05056 D01023 B05042 B05052 D12012 D12013 D12016 3 D12010 D12011 D12015 D12018 3 D12010 D12011 D12017 D12020 11 D01047 D01048 B15015 B29002 B21076 R04012 B06030 R02012 B05030 B21075 B21066 D12021 6 D01047 R01003 D01049 B11012 B11011 B21067 D12022 15 D01047 B08022 B11012 B11050 B22070 B22026 D12041 B10050 B21068 B21071 B21072 B21073 D12042 B21062 B15011 D12023 7 D01047 R03003 B08022 B12061 B22050 B21069 B21085 D12024 11 D12020 B08060 B08022 B08060 B08022 B25014 B22101 B22097 B22098 B22099 B22100 D12025 11 D12019 B08060 B08022 B08060 B08022 B25014 B22101 B22097 B22098 B22099 B22100 D12026 19 D01046 D01011 D01013 D01023 D12031 R01004 D12030 B21110 D01023 D21027 B21111 D01023 D21027 B21112 D01023 D21027 B21113 D01023 D21027 D12027 9 D01047 R05009 D01023 B07021 B12061 B07021 B12061 B21085 B21070 D12031 8 B05034 B06034 B21109 B11081 B11082 B21101 B21102 B21103 D12032 4 B21120 B21121 B13055 B21122 D12033 4 B02104 B08022 B12063 B12065 D12042 6 B21077 B21078 B21079 B21080 B21081 B21082 D12045 21 B01007 B02019 B01096 B25061 B05040 D01011 D01013 D01021 B07002 B12180 B12181 B12182 B12183 B12184 B12185 B02174 B21086 B12186 B21087 B12187 B33043 D13009 3 B21001 R01000 B21001 D13010 3 B21036 R01000 B21036 D13031 4 B06002 B06012 R01000 B30001 D13032 4 B05002 B05012 R01000 D13031 D13041 9 B06002 R10000 R04000 B06012 R01000 B30001 B06012 R01000 B30001 D13042 4 B05002 B05012 R01000 D13041 D13043 11 B06002 B05002 B05012 R12000 R10000 R04000 B06012 R01000 B30001 R01000 B30001 D15001 5 B01011 D01011 D01012 D01023 D06001 D15002 5 B01011 D01011 D01012 D01023 D06004 D16001 10 D01011 B04004 D01023 B01021 B02041 B19001 B10051 B19002 B19003 B19004 D16002 15 B08021 B04001 B04002 B04003 B04004 B04005 B01033 B08021 B04001 B04002 B04003 B04004 B04005 B07002 B07002 D16003 10 R09000 B08011 B08007 R04000 B05002 B06002 B10002 B11002 B08007 B08011 D16004 11 R10000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B11031 B08007 B08011 D16005 9 R08000 B08005 B08007 B05002 B06002 B01026 B19001 B08007 B08005 D16006 12 R11000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B20011 B20012 B08007 B08011 D16007 10 R09000 B08011 B08007 R04000 B05002 B06002 B19005 B19006 B08007 B08011 D16008 11 R10000 B08001 B08007 B08023 R03000 B05002 B06002 B10002 B08023 B08007 B08001 D16009 11 R10000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B20041 B08007 B08011 D16010 8 R07000 B08011 B08007 B01022 B05002 B06002 B08007 B08011 D16011 17 R16000 B08011 B01022 B08007 R02000 B05002 B06002 B08021 B04001 B04002 B04003 B04004 B04005 B20090 B08021 B08007 B08011 D16020 5 B01023 B01025 B01027 D01011 D01012 D16021 23 D01023 B02041 B19001 B19007 B19005 B19006 B19008 B08005 B10004 B08005 B10004 B19007 B08005 B08021 B04075 B11040 B19007 R05004 B05021 B05021 R02002 B19003 B19004 D16022 23 B01032 B02041 B19001 B19010 R18000 B08021 B04014 B08005 D01023 B19005 B19006 B10004 B11041 B08021 B04075 B11040 B19008 R05004 B05021 B05021 R02002 B19003 B19004 D16026 2 D16020 D16021 D18001 2 D01025 B24011 D18003 4 D01026 B24005 B24004 B24021 D18004 6 D01025 B04023 B13011 B24005 B24004 B24022 D21001 6 B02101 B02114 B02105 B02106 B02107 B02121 D21003 4 B21051 B21014 B21017 B21030 D21004 4 D01031 B02003 R01000 D21003 D21005 12 B25004 B02121 B02122 B02123 B02124 B02125 B02126 B02127 B02128 B02129 B02130 B02131 D21006 4 B25001 B25002 B25003 B25005 D21007 8 B25009 B25010 B25011 B25012 B25013 B25015 B25016 B25017 D21008 3 B25006 B25007 B25008 D21009 2 B25018 B25019 D21010 13 B02101 B07002 B02102 B02103 B02104 B02105 B02106 B02107 B02108 B02109 B02110 B02132 B02133 D21011 3 B30031 B30032 B29002 D21012 2 R01000 B02135 D35001 4 B08035 B35001 B08036 D01001 D35002 4 B08035 B35001 B08036 B01033 D35003 6 B08021 B04001 B04002 B04003 B04004 B04073 D35004 7 B08021 B04004 B08021 B04004 B35000 D01001 B35011 D35005 7 B08021 B04004 B08021 B04004 B35000 B01001 B35011 D35006 7 B08021 B04004 B08021 B04004 B35000 B01003 B35011 D35007 9 B08021 B04004 B08021 B04004 B35000 B01001 R02000 B01002 B35011 D35010 3 D35002 D35003 D35007 dballe-7.7/tables/D000000002001200.txt0000644000175000017500000107105612652630043013271 00000000000000 300002 2 000002 000003 300003 3 000010 000011 000012 300004 9 300003 000013 000014 000015 000016 000017 000018 000019 000020 300010 4 300003 101000 031001 000030 301001 2 001001 001002 301002 3 001003 001004 001005 301003 3 001011 001012 001013 301004 4 001001 001002 001015 002001 301011 3 004001 004002 004003 301012 2 004004 004005 301013 3 004004 004005 004006 301021 2 005001 006001 301022 3 005001 006001 007001 301023 2 005002 006002 301024 3 005002 006002 007001 301025 3 301023 004003 301012 301026 7 301021 004003 004003 004004 004004 004005 004005 301031 5 301001 002001 301011 301012 301022 301032 5 301001 002001 301011 301012 301024 301033 5 001005 002001 301011 301012 301021 301034 5 001005 002001 301011 301012 301023 301035 7 001005 001012 001013 002001 301011 301012 301023 301036 5 301003 002001 301011 301012 301023 301037 6 301001 002011 002012 301011 301012 301022 301038 6 301001 002011 002012 301011 301012 301024 301039 6 301003 002011 002012 301011 301012 301023 301040 6 301003 002011 002012 301011 301012 301024 301041 5 001007 002021 002022 301011 301012 301042 2 301041 301021 301043 5 001007 002023 301011 301013 301021 301044 5 001007 002024 301011 301013 301021 301045 9 301011 301012 201138 202131 004006 201000 202000 304030 304031 301046 10 001007 001012 002048 021119 025060 202124 002026 002027 202000 005040 301047 15 001007 025060 001033 001034 001012 301045 002021 301011 301012 201138 202131 004006 201000 202000 301023 301048 14 002104 002121 002113 002026 002027 002111 002140 202127 001013 202126 007001 202000 025010 021064 301049 5 002111 002112 021062 021063 021065 301051 6 001006 002061 301011 301012 301021 008004 301055 7 001005 002001 301011 301012 301021 001012 001014 301062 3 101000 031001 301001 301065 8 001006 001008 002001 002002 002005 002062 002070 002065 301066 6 301011 301013 301023 007004 002064 008004 301071 5 001007 001031 002020 002028 002029 301072 4 301071 301011 301013 301021 301090 6 301004 301011 301012 301021 007030 007031 301091 10 002180 002181 002182 002183 002184 002179 002186 002187 002188 002189 301193 5 001007 001031 002196 002221 002222 301194 9 001194 001012 001013 002011 002012 301011 301012 301023 007001 301195 9 001195 001012 001013 002011 002012 301011 301012 301023 007001 301196 7 301003 002011 002012 301011 301012 301023 007001 301197 9 001006 001008 002061 002062 002002 002005 002070 002063 002001 301200 2 001032 033194 301201 2 101003 033193 301202 2 001031 001032 301237 12 001007 001012 002021 301011 004004 004005 201138 202131 004006 201000 202000 301023 301238 14 002104 002121 002113 002026 002027 002111 002192 202127 001013 202126 007001 202000 025010 021194 301239 5 002111 002112 021192 021193 021195 301240 5 201131 202129 022021 201000 202000 301241 5 201141 202130 007001 201000 202000 301242 6 021207 021208 021209 021210 021211 021212 301250 4 301193 301011 301013 301021 302001 4 010004 010051 010061 010063 302002 5 010004 007004 010003 010061 010063 302003 9 011011 011012 012004 012006 013003 020001 020003 020004 020005 302004 7 020010 008002 020011 020013 020012 020012 020012 302005 4 008002 020011 020012 020013 302006 4 010004 010051 010062 010063 302011 3 302001 302003 302004 302012 3 302002 302003 302004 302013 5 302006 302003 101000 031001 302005 302021 3 022001 022011 022021 302022 3 022002 022012 022022 302023 3 022003 022013 022023 302024 3 302022 101002 302023 302051 12 010004 010051 007004 010003 012004 012051 012016 012017 013004 102004 008051 008020 302069 4 007032 007033 033041 020001 302070 8 007032 007033 011001 011002 011043 011041 011016 011017 302071 14 007032 007033 008021 004025 011001 011002 008021 103002 004025 011043 011041 004025 011016 011017 302072 5 007032 007033 012101 012103 013003 302073 7 020010 105004 008002 020011 020012 033041 020013 302074 4 020003 004025 020004 020005 302075 5 008021 004025 013055 013058 008021 302076 7 002021 020022 026020 020023 020024 020025 020026 302077 12 007032 007033 004025 012111 012112 007032 004025 012112 002176 020062 002177 013013 302078 4 002176 020062 002177 013013 302079 5 007032 002175 002178 004025 013011 302080 3 002185 004025 013033 302081 2 004025 014031 302082 7 004025 014002 014004 014016 014028 014029 014030 302083 8 004025 008023 010004 011001 011002 012101 013003 008023 302205 5 201131 202129 022021 201000 202000 302206 9 302205 201130 202129 022011 201000 202000 022001 011001 011002 302207 5 022193 022194 022195 022196 022197 302250 5 102000 031001 020193 020194 020012 303001 3 007003 011001 011002 303002 3 007004 011001 011002 303003 4 007004 010003 012001 012003 303004 6 007004 010003 012001 012003 011001 011002 303011 4 007003 008001 011001 011002 303012 4 007004 008001 011001 011002 303013 7 007004 008001 010003 012001 013003 011001 011002 303014 7 007004 008001 010003 012001 012003 011001 011002 303021 4 007004 007004 204007 031021 303022 3 303021 010003 204000 303023 3 303021 012001 204000 303024 3 303021 013016 204000 303025 5 002025 204007 031021 012063 204000 303026 6 007004 008003 204007 031021 012001 204000 303027 5 007004 204007 031021 010003 204000 303031 6 007004 008003 007021 007022 008012 012061 303032 2 020011 020016 303033 2 020010 020016 303041 8 002152 002023 007004 011001 011002 002153 002154 012071 303249 7 002252 104000 031001 002199 007004 007004 013003 303250 8 002252 002023 007004 011001 011002 002197 002198 012193 303251 8 002252 105000 031001 002254 002251 002197 002198 012063 303252 8 002252 105000 031001 002254 002251 002197 002198 012194 304001 5 008003 010004 012001 011001 011002 304002 4 008003 010004 011001 011002 304003 2 008003 012001 304004 4 008003 010004 020010 012001 304005 4 002024 007004 007004 013003 304006 3 014001 014001 014003 304011 27 002163 002164 008012 007024 002057 008021 004001 004002 004003 004004 008021 004024 110004 008021 004004 004005 004006 008021 004004 004005 004006 011001 011002 103010 002163 007004 012001 304030 3 027031 028031 010031 304031 3 001041 001042 001043 304032 5 002153 002154 020081 020082 020012 304033 8 002152 002166 002167 002153 002154 012075 012076 012063 304034 9 102004 027001 028001 007022 005043 020010 020016 033003 010040 304228 3 005217 006217 007217 304229 3 001208 001209 001210 304250 27 002231 002232 008012 007024 002057 008021 004001 004002 004003 004004 008021 004024 110004 008021 004004 004005 004006 008021 004004 004005 004006 011001 011002 103010 002231 007004 012001 305003 5 301012 004065 101000 031001 305001 305006 6 013072 013082 013019 012001 013073 013060 305007 6 301029 301012 004065 101000 031001 305006 305008 2 305006 012030 305009 6 301029 301012 004065 101000 031001 305008 305011 6 301029 301012 004065 101000 031001 305010 305018 8 301029 301012 004065 103000 031001 305008 305016 305017 306001 5 002032 102000 031001 007062 022042 306002 3 002031 022004 022031 306003 4 002002 011011 011012 012004 306004 7 002032 002033 103000 031001 007062 022043 022062 306005 6 002031 103000 031001 007062 022004 022031 306006 3 306003 306002 022063 306007 6 001012 001014 306008 004024 027003 028003 306008 3 002034 002035 002036 306020 4 306024 102006 022038 022039 306021 7 001075 301011 301012 022122 022123 012001 303002 306022 5 001075 301011 301012 022038 022039 306023 8 001015 301023 301011 301012 022038 022039 022120 022121 306024 8 001075 301011 301012 022042 022120 022121 004025 004015 307001 2 301031 302011 307002 2 301032 302011 307003 4 307001 101000 031001 302005 307004 4 307002 101000 031001 302005 307005 3 307001 101004 302005 307006 3 307002 101004 302005 307007 2 301031 302012 307008 2 301032 302012 307009 2 301031 302013 307011 16 001063 002001 301011 301012 301024 007006 011001 011016 011017 011002 011041 007006 012001 012003 010052 020009 307012 5 103000 031001 008023 005021 020001 307013 8 106000 031001 001064 008014 020061 008014 020061 020018 307014 3 101000 031001 020019 307015 8 101000 031001 302005 008002 020011 020012 020013 020002 307016 3 101000 031001 020020 307017 3 101000 031001 011070 307018 16 008016 102000 031001 008017 301012 104000 031001 007006 011001 011002 011041 020009 101000 031001 020001 307014 307020 3 307011 307014 307016 307021 9 307011 307012 307013 307014 307015 307016 307017 307018 307015 307022 31 001015 301011 301012 301022 008021 004025 010004 012001 013003 033038 008022 106025 002020 001050 005021 007021 015031 015032 008060 015033 015034 008060 015033 015034 015035 201131 202129 013016 202000 201000 015011 307030 2 015001 015002 307031 7 008022 008023 015001 008023 015001 008023 015002 307041 7 301001 001015 301022 301011 301012 301070 307030 307042 9 301001 001015 301022 301011 301012 008021 004025 301070 307031 307043 7 301001 001015 301024 301011 301012 301074 307030 308001 3 301033 302011 022042 308002 3 301034 302011 022042 308003 3 301035 302011 022042 308004 3 301036 302011 022042 308005 2 308004 302024 308006 8 010004 010061 010063 011001 011002 012004 013003 022042 308007 4 301055 302011 007062 022042 309001 4 301037 101000 031001 303011 309002 4 301038 101000 031001 303011 309003 4 301037 101000 031001 303012 309004 4 301038 101000 031001 303012 309005 5 301037 302004 101000 031001 303013 309006 5 301038 302004 101000 031001 303013 309007 5 301037 302004 101000 031001 303014 309008 5 301038 302004 101000 031001 303014 309011 4 301039 101000 031001 303011 309012 4 301039 101000 031001 303012 309013 5 301039 302004 101000 031001 303013 309014 5 301039 302004 101000 031001 303014 309015 4 301040 101000 031001 303011 309016 4 301040 101000 031001 303012 309017 5 301040 302004 101000 031001 303013 309018 5 301040 302004 101000 031001 303014 309019 5 301031 002003 101000 031001 303011 309020 8 301031 002003 104000 031001 007003 011003 011004 011005 309030 8 015004 015005 104000 031001 004015 008006 007004 015003 309040 3 301075 301076 309030 309042 4 307042 301075 301076 309030 309194 5 301194 302004 101000 031001 303014 309195 5 301195 302004 101000 031001 303014 309196 5 301196 302004 101000 031001 303014 310001 5 301042 303031 303032 101026 303025 310002 5 301042 303031 303032 101009 303023 310003 5 301042 303031 303032 101006 303023 310004 5 301042 303031 303032 101003 303024 310005 6 301042 303031 303033 101000 031001 303025 310006 6 301042 303031 303033 101000 031001 303023 310007 6 301042 303031 303033 101000 031001 303024 310008 8 310011 101019 310012 002150 025079 025080 033032 014045 310009 3 310011 101015 310012 310010 3 310011 101005 310012 310011 45 008070 001033 001034 008070 001033 001034 001007 002048 005040 025075 201133 005041 201000 005043 025070 033030 033031 004001 004002 004003 004004 004005 202131 201138 004006 201000 202000 005001 006001 202126 007001 202000 007024 005021 007025 005022 033033 002151 012064 002151 012064 002151 012064 002151 012064 310012 10 002150 025076 025077 025078 033032 201132 202129 012063 202000 201000 310013 62 001007 005040 004001 004002 004003 004004 004005 004006 005001 006001 007025 005043 025085 201131 202129 002150 008023 008072 014027 008072 014027 002150 008023 008072 014027 008072 014027 002150 008023 008072 014027 008072 014027 202000 201000 201132 202129 002150 008023 008072 012063 008072 012063 002150 008023 008072 012063 008072 012063 008023 008072 012063 008072 012063 002150 008023 008072 012063 008072 012063 202000 201000 310014 3 301072 303041 304011 310015 13 301072 007024 010002 303041 101003 304032 002152 002024 007004 007004 013003 101003 304033 310016 13 301072 007024 010002 303041 101012 304032 002152 002024 007004 007004 013003 101012 304033 310020 6 310022 301011 301013 301021 304034 310021 310021 10 108000 031001 201131 202129 007004 007004 202000 201000 015020 010002 310022 4 001007 002019 001033 002172 310023 17 301072 030021 030022 008012 007024 007025 010002 101012 304032 105002 002152 002024 007004 007004 013003 101012 304033 310024 17 301072 030021 030022 008012 007024 007025 010002 101003 304032 105002 002152 002024 007004 007004 013003 101003 304033 310025 61 001007 008021 004001 004002 004003 004004 004005 201138 202131 004006 202000 201000 201132 005041 201000 201129 005043 201000 005002 006002 013040 020029 104024 005042 012163 021083 021084 115003 004001 004002 004003 201142 202131 004026 202000 201000 005001 006001 201138 202129 007001 202000 201000 008021 004001 004002 004003 004004 004005 005040 101003 012070 025054 101004 025055 008007 104028 005002 006002 002111 005021 310029 12 110000 031001 201138 202130 007004 007004 202000 201000 015020 010002 012101 013098 310030 6 310022 301011 301013 301021 304034 310029 310050 14 310051 310052 101000 031002 310053 101004 310054 020010 310052 101015 310053 310052 101004 310053 310051 16 001007 005040 201133 005041 201000 201132 025070 201000 202126 007001 202000 007025 005022 102009 002151 012064 310052 12 002019 301011 301012 202131 201138 004006 201000 202000 301021 007024 005021 005043 310053 6 201134 005042 201000 025076 033032 012163 310054 13 201134 005042 201000 025076 033032 201131 202129 102002 008023 014027 008023 202000 201000 310055 8 310051 310052 102020 025076 025051 101000 031002 025050 310193 5 301250 303250 302250 303249 303251 310194 5 301250 303250 302250 303249 303252 310195 3 301250 303250 304250 310196 3 301250 303249 303251 311001 9 301051 007002 012001 011001 011002 011031 011032 011033 020041 311002 4 301065 301066 311003 311004 311003 5 010070 011001 011002 012001 013002 311004 18 101000 031000 011034 101000 031000 011035 101000 031000 011075 101000 031000 011076 101000 031000 033025 101000 031000 033026 311005 13 001008 001023 301021 301011 301013 007010 008009 011001 011002 011031 011036 012101 033025 311006 6 007010 011001 011002 002064 012101 012103 311193 16 301197 301011 301012 301023 008004 007004 008021 011001 011002 011031 011034 011035 012001 012003 013003 020041 312001 2 301043 304001 312002 2 301043 304002 312003 2 301042 304003 312004 2 301042 304004 312005 2 301042 020014 312006 2 301044 304005 312007 2 301042 304006 312010 6 001007 005040 002021 005041 004001 004043 312011 9 202131 201149 004006 201000 202126 010002 202000 005043 005053 312012 6 202129 201132 101019 012063 201000 202000 312013 6 005042 202129 201135 012063 201000 202000 312014 8 312010 312011 105056 301023 005042 005052 312012 312013 312015 10 109011 301023 005042 005052 202129 201132 101004 012063 202000 201000 312016 3 312010 312011 312015 312017 10 109008 301023 005042 005052 202129 201132 101003 012063 202000 201000 312018 3 312010 312011 312017 312019 13 301047 301048 015015 029002 021076 106012 201129 006030 201000 102012 005030 021075 021066 312020 11 301047 301048 015015 029002 021076 104012 006030 102012 005030 021075 021066 312021 6 301047 101003 301049 011012 011011 021067 312022 15 301047 008022 011012 011050 022070 022026 312041 010050 021068 021071 021072 021073 312042 021062 015011 312023 7 301047 103003 008022 012061 022050 021069 021085 312024 11 312020 008060 008022 008060 008022 025014 022101 022097 022098 022099 022100 312025 11 312019 008060 008022 008060 008022 025014 022101 022097 022098 022099 022100 312026 19 301046 301011 301013 301023 312031 101004 312030 021110 301023 321027 021111 301023 321027 021112 301023 321027 021113 301023 321027 312027 9 301047 105009 301023 007021 012061 007021 012061 021085 021070 312028 26 301046 301011 301013 301023 008025 201136 004006 201000 312031 312032 101004 312030 101002 312033 021110 301023 321028 021111 301023 321028 021112 301023 321028 021113 301023 321028 312030 13 201130 202129 011012 202000 201000 011052 201135 202130 011011 202000 201000 011053 021104 312031 8 005034 006034 021109 011081 011082 021101 021102 021103 312032 4 021120 021121 013055 021122 312033 4 002104 008022 012063 012065 312041 5 201141 202130 007001 201000 202000 312042 6 021077 021078 021079 021080 021081 021082 312045 21 001007 002019 001096 025061 005040 301011 301013 301021 007002 012180 012181 012182 012183 012184 012185 002174 021086 012186 021087 012187 033043 312050 23 001007 002019 001096 025061 005040 301011 301013 301021 007025 005022 010080 027080 008003 007004 013093 008003 201131 202129 007004 007004 202000 201000 013095 312051 48 001007 002019 001096 025061 005040 008075 301011 301013 301021 001012 201131 001013 201000 010032 010033 010034 007002 008012 025110 025111 025102 002104 025103 025104 025105 025106 025107 025108 002111 002121 002026 002027 021130 021131 021132 021133 021064 025014 021134 107018 005030 105024 201130 006030 201000 021135 021136 033044 312052 77 001007 002019 001096 025061 005040 025120 025121 025124 025125 025122 025123 301011 301013 301021 007002 002119 033047 010081 010082 010083 010084 002116 002117 002118 002156 002157 014055 022150 022151 022152 022153 022154 022155 022156 022157 022158 022159 021137 021138 021139 021140 021141 021142 010085 010086 010087 010088 010089 010090 010091 010092 010093 011002 025126 025127 025128 025129 025130 025131 025132 025133 025134 025135 025136 025137 013096 013097 011095 011096 012188 012189 002158 002159 033052 033053 021143 021144 312053 54 001007 002019 001096 025061 005040 008075 301011 301013 301021 001012 201131 001013 201000 010032 010033 010034 007002 008012 025110 025111 025102 002104 025103 025104 025105 025106 025107 025108 011001 011002 022160 025138 201130 202129 022021 202000 201000 033048 033049 002026 002027 021130 021131 021132 021133 025014 106036 005030 104024 201130 006030 201000 022161 033044 312200 10 301237 301238 029002 021206 104012 006232 102012 005232 021205 021196 312201 6 301237 101003 301239 011012 011011 021197 312202 13 301237 008022 011012 011050 301240 022243 301241 010050 021198 021201 021202 021203 301242 312203 8 301237 008022 012061 022050 021204 021199 021214 021215 312204 12 312201 001031 011012 011011 021200 021213 004004 008021 004024 055003 011012 011011 312207 3 312202 301202 033191 312208 17 301202 008022 008021 301011 301013 301023 302205 011002 001007 002021 301011 301013 301023 001032 001192 302205 011002 312209 11 301202 001192 301011 301013 301023 302206 104000 022192 102000 005232 022191 312210 13 312202 021192 015202 301011 004004 004005 201138 202131 004006 201000 202000 304228 304229 312211 19 301046 301011 301013 301023 312031 101004 312030 021110 101004 312212 021111 101004 312212 021112 101004 312212 021113 101004 312212 312212 2 301023 321027 313009 4 021001 101000 031001 021001 313010 4 021036 101000 031001 021036 313031 5 006002 006012 101000 031002 030001 313032 5 005002 005012 101000 031002 313031 313041 13 006002 110000 031001 104000 031001 006012 101000 031012 030001 006012 101000 031001 030001 313042 5 005002 005012 101000 031002 313041 313043 16 006002 005002 005012 112000 031001 110000 031001 104000 031001 006012 101000 031011 030001 101000 031001 030001 315001 5 001011 301011 301012 301023 306001 315002 5 001011 301011 301012 301023 306004 316001 10 301011 004004 301023 001021 002041 019001 010051 019002 019003 019004 316002 15 008021 004001 004002 004003 004004 004005 001033 008021 004001 004002 004003 004004 004005 007002 007002 316003 12 110000 031001 008011 008007 104000 031001 005002 006002 010002 011002 008007 008011 316004 13 111000 031001 008011 008007 007002 007002 102000 031001 005002 006002 011031 008007 008011 316005 10 108000 031001 008005 008007 005002 006002 001026 019001 008007 008005 316006 14 112000 031001 008011 008007 007002 007002 102000 031001 005002 006002 020011 020012 008007 008011 316007 12 110000 031001 008011 008007 104000 031001 005002 006002 019005 019006 008007 008011 316008 13 111000 031001 008001 008007 008023 103000 031001 005002 006002 010002 008023 008007 008001 316009 13 111000 031001 008011 008007 007002 007002 102000 031001 005002 006002 020041 008007 008011 316010 9 107000 031001 008011 008007 001022 005002 006002 008007 008011 316011 19 116000 031001 008011 001022 008007 102000 031001 005002 006002 008021 004001 004002 004003 004004 004005 020090 008021 008007 008011 316022 24 001032 002041 019001 019010 118000 031001 008021 004014 008005 301023 019005 019006 010004 011041 008021 004075 011040 019008 105004 005021 005021 102002 019003 019004 318001 2 301025 024011 318003 4 301026 024005 024004 024021 318004 6 301025 004023 013011 024005 024004 024022 321001 6 002101 002114 002105 002106 002107 002121 321003 4 021051 021014 021017 021030 321004 5 301031 002003 101000 031001 321003 321005 12 025004 002121 002122 002123 002124 002125 002126 002127 002128 002129 002130 002131 321006 4 025001 025002 025003 025005 321007 8 025009 025010 025011 025012 025013 025015 025016 025017 321008 3 025006 025007 025008 321009 2 025018 025019 321010 13 002101 007002 002102 002103 002104 002105 002106 002107 002108 002109 002110 002132 002133 321011 3 030031 030032 029002 321012 3 101000 031001 002135 321021 15 002003 002101 201130 002106 201000 201132 202130 002121 202000 201000 201133 202129 025001 202000 201000 321022 11 010007 204001 031021 011001 204000 011002 204001 031021 011006 204000 021030 321023 9 007007 021091 021030 202129 021014 201129 021017 202000 201000 321024 7 007007 204002 031021 012007 011006 204000 021030 321025 17 007007 021091 021030 202129 021014 201129 021017 202000 201000 021092 021030 025092 201129 202129 021017 202000 201000 321026 10 010007 204001 031021 012007 025091 011071 011072 011073 011074 204000 321027 18 021118 202129 201132 002112 201000 201131 002111 201000 202000 002104 021105 021106 021107 021114 021115 021116 008018 021117 321028 18 021118 202129 201132 002112 201000 201131 002111 201000 202000 002104 021123 021106 021107 021114 021115 021116 008018 021117 dballe-7.7/tables/D990203.txt0000644000175000017500000052523112652630043012431 00000000000000 D00002 2 B00002 B00003 D00003 3 B00010 B00011 B00012 D00004 9 D00003 B00013 B00014 B00015 B00016 B00017 B00018 B00019 B00020 D00010 3 D00003 R01000 B00030 D01001 2 B01001 B01002 D01002 3 B01003 B01004 B01005 D01003 3 B01011 B01012 B01013 D01004 4 B01001 B01002 B01015 B02001 D01011 3 B04001 B04002 B04003 D01012 2 B04004 B04005 D01013 3 B04004 B04005 B04006 D01021 2 B05001 B06001 D01022 3 B05001 B06001 B07001 D01023 2 B05002 B06002 D01024 3 B05002 B06002 B07001 D01025 3 D01023 B04003 D01012 D01026 7 D01021 B04003 B04003 B04004 B04004 B04005 B04005 D01029 3 B01018 B02001 D01011 D01030 4 B01018 B02001 D01011 D01024 D01031 5 D01001 B02001 D01011 D01012 D01022 D01032 5 D01001 B02001 D01011 D01012 D01024 D01033 5 B01005 B02001 D01011 D01012 D01021 D01034 5 B01005 B02001 D01011 D01012 D01023 D01035 7 B01005 B01012 B01013 B02001 D01011 D01012 D01023 D01036 5 D01003 B02001 D01011 D01012 D01023 D01037 6 D01001 B02011 B02012 D01011 D01012 D01022 D01038 6 D01001 B02011 B02012 D01011 D01012 D01024 D01039 6 D01003 B02011 B02012 D01011 D01012 D01023 D01040 6 D01003 B02011 B02012 D01011 D01012 D01024 D01041 5 B01007 B02021 B02022 D01011 D01012 D01042 2 D01041 D01021 D01043 5 B01007 B02023 D01011 D01013 D01021 D01044 5 B01007 B02024 D01011 D01013 D01021 D01049 5 B02111 B02112 B21062 B21063 B21065 D01051 6 B01006 B02061 D01011 D01012 D01021 B08004 D01055 7 B01005 B02001 D01011 D01012 D01021 B01012 B01014 D01062 2 R01000 D01001 D01065 8 B01006 B01008 B02001 B02002 B02005 B02062 B02070 B02065 D01066 6 D01011 D01013 D01023 B07004 B02064 B08004 D01070 3 B02143 B02142 B02144 D01071 5 B01007 B01031 B02020 B02028 B02029 D01072 4 D01071 D01011 D01013 D01021 D01074 4 B02143 B02142 B02145 B02146 D01075 6 D01001 B01015 D01024 B08021 D01011 D01012 D01076 3 B02011 B02143 B02142 D01090 6 D01004 D01011 D01012 D01021 B07030 B07031 D01091 10 B02180 B02181 B02182 B02183 B02184 B02179 B02186 B02187 B02188 B02189 D01193 5 001007 001031 002196 002221 002222 D01250 4 D01193 D01011 D01013 D01021 D02001 4 B10004 B10051 B10061 B10063 D02002 5 B10004 B07004 B10003 B10061 B10063 D02003 9 B11011 B11012 B12004 B12006 B13003 B20001 B20003 B20004 B20005 D02004 7 B20010 B08002 B20011 B20013 B20012 B20012 B20012 D02005 4 B08002 B20011 B20012 B20013 D02006 4 B10004 B10051 B10062 B10063 D02011 3 D02001 D02003 D02004 D02012 3 D02002 D02003 D02004 D02013 4 D02006 D02003 R01000 D02005 D02021 3 B22001 B22011 B22021 D02022 3 B22002 B22012 B22022 D02023 3 B22003 B22013 B22023 D02024 3 D02022 R01002 D02023 D02051 12 B10004 B10051 B07004 B10003 B12004 B12051 B12016 B12017 B13004 R02004 B08051 B08020 D02069 4 B07032 B07033 B33041 B20001 D02070 8 B07032 B07033 B11001 B11002 B11043 B11041 B11016 B11017 D02071 14 B07032 B07033 B08021 B04025 B11001 B11002 B08021 R03002 B04025 B11043 B11041 B04025 B11016 B11017 D02072 5 B07032 B07033 B12101 B12103 B13003 D02073 7 B20010 R05004 B08002 B20011 B20012 B33041 B20013 D02074 4 B20003 B04025 B20004 B20005 D02075 5 B08021 B04025 B13055 B13058 B08021 D02076 7 B02021 B20022 B26020 B20023 B20024 B20025 B20026 D02077 12 B07032 B07033 B04025 B12111 B12112 B07032 B04025 B12112 B02176 B20062 B02177 B13013 D02078 4 B02176 B20062 B02177 B13013 D02079 5 B07032 B02175 B02178 B04025 B13011 D02080 3 B02185 B04025 B13033 D02081 2 B04025 B14031 D02082 7 B04025 B14002 B14004 B14016 B14028 B14029 B14030 D02083 8 B04025 B08023 B10004 B11001 B11002 B12101 B13003 B08023 D03001 3 B07003 B11001 B11002 D03002 3 B07004 B11001 B11002 D03003 4 B07004 B10003 B12001 B12003 D03004 6 B07004 B10003 B12001 B12003 B11001 B11002 D03011 4 B07003 B08001 B11001 B11002 D03012 4 B07004 B08001 B11001 B11002 D03013 7 B07004 B08001 B10003 B12001 B13003 B11001 B11002 D03014 7 B07004 B08001 B10003 B12001 B12003 B11001 B11002 D03031 6 B07004 B08003 B07021 B07022 B08012 B12061 D03032 2 B20011 B20016 D03033 2 B20010 B20016 D03041 8 B02152 B02023 B07004 B11001 B11002 B02153 B02154 B12071 D03250 8 B02252 B02023 B07004 B11001 B11002 B02197 B02198 B12193 D04001 5 B08003 B10004 B12001 B11001 B11002 D04002 4 B08003 B10004 B11001 B11002 D04003 2 B08003 B12001 D04004 4 B08003 B10004 B20010 B12001 D04005 4 B02024 B07004 B07004 B13003 D04006 3 B14001 B14001 B14003 D04011 27 B02163 B02164 B08012 B07024 B02057 B08021 B04001 B04002 B04003 B04004 B08021 B04024 R10004 B08021 B04004 B04005 B04006 B08021 B04004 B04005 B04006 B11001 B11002 R03010 B02163 B07004 B12001 D04030 3 B27031 B28031 B10031 D04031 3 B01041 B01042 B01043 D04032 5 B02153 B02154 B20081 B20082 B20012 D04033 8 B02152 B02166 B02167 B02153 B02154 B12075 B12076 B12063 D04034 9 R02004 B27001 B28001 B07022 B05043 B20010 B20016 B33003 B10040 D04250 27 B02231 B02232 B08012 B07024 B02057 B08021 B04001 B04002 B04003 B04004 B08021 B04024 R10004 B08021 B04004 B04005 B04006 B08021 B04004 B04005 B04006 B11001 B11002 R03010 B02231 B07004 B12001 D05001 4 B11001 B11002 B13060 B13071 D05002 11 D01012 B12001 B13003 B14051 B13060 B13072 B13080 B13081 B13082 B13083 B13084 D05003 4 D01012 B04065 R01000 D05001 D05004 3 D01030 D05002 D05003 D05006 8 B13072 B13082 B13019 C07005 C01004 B12001 B13073 B13060 D05007 5 D01029 D01012 B04065 R01000 D05006 D05008 4 D05006 C07005 C01004 B12030 D05009 5 D01029 D01012 B04065 R01000 D05008 D05010 3 D05008 B02091 B02091 D05011 5 D01029 D01012 B04065 R01000 D05010 D05016 7 B14021 B07004 B13003 B11002 B11001 B11041 B11043 D05017 5 B13080 B13081 B13083 B13085 B13084 D05018 7 D01029 D01012 B04065 R03000 D05008 D05016 D05017 D06001 4 B02032 R02000 B07062 B22042 D06002 3 B02031 B22004 B22031 D06003 4 B02002 B11011 B11012 B12004 D06004 6 B02032 B02033 R03000 B07062 B22043 B22062 D06005 5 B02031 R03000 B07062 B22004 B22031 D06006 3 D06003 D06002 B22063 D06007 6 B01012 B01014 D06008 B04024 B27003 B28003 D06008 3 B02034 B02035 B02036 D06020 8 B01075 D01011 D01012 B22042 B22120 B22121 B04075 B04065 D06021 7 B01075 D01011 D01012 B22122 B22123 B12001 D03002 D06022 5 B01075 D01011 D01012 B22038 B22039 D06023 8 B01015 D01023 D01011 D01012 B22038 B22039 B22120 B22121 D06024 4 D06020 R02000 B22038 B22039 D07001 2 D01031 D02011 D07002 2 D01032 D02011 D07003 3 D07001 R01000 D02005 D07004 3 D07002 R01000 D02005 D07005 3 D07001 R01004 D02005 D07006 3 D07002 R01004 D02005 D07007 2 D01031 D02012 D07008 2 D01032 D02012 D07009 2 D01031 D02013 D07011 16 B01063 B02001 D01011 D01012 D01024 B07006 B11001 B11016 B11017 B11002 B11041 B07006 B12001 B12003 B10052 B20009 D07012 4 R03000 B08023 B05021 B20001 D07013 7 R06000 B01064 B08014 B20061 B08014 B20061 B20018 D07014 2 R01000 B20019 D07015 3 R01000 D02005 B20002 D07016 2 R01000 B20020 D07017 2 R01000 B11070 D07018 13 B08016 R02000 B08017 D01012 R04000 B07006 B11001 B11002 B11041 B20009 R01000 B20001 D07014 D07020 3 D07011 D07014 D07016 D07021 9 D07011 D07012 D07013 D07014 D07015 D07016 D07017 D07018 D07015 D07030 2 B15001 B15002 D07031 7 B08022 B08023 B15001 B08023 B15001 B08023 B15002 D07041 7 D01001 B01015 D01024 D01011 D01012 D01070 D07030 D07042 9 D01001 B01015 D01024 D01011 D01012 B08021 B04025 D01070 D07031 D07043 7 D01001 B01015 D01024 D01011 D01012 D01074 D07030 D07044 9 D01001 B01015 D01024 D01011 D01012 B08021 B04025 D01074 D07031 D07060 2 B07061 B12030 D07061 3 D01031 R01005 D07060 D07062 3 D01032 R01005 D07060 D07063 2 B07061 B12130 D08001 3 D01033 D02011 B22042 D08002 3 D01034 D02011 B22042 D08003 3 D01035 D02011 B22042 D08004 3 D01036 D02011 B22042 D08005 2 D08004 D02024 D08006 8 B10004 B10061 B10063 B11001 B11002 B12004 B13003 B22042 D08007 4 D01055 D02011 B07062 B22042 D09001 3 D01037 R01000 D03011 D09002 3 D01038 R01000 D03011 D09003 3 D01037 R01000 D03012 D09004 3 D01038 R01000 D03012 D09005 4 D01037 D02004 R01000 D03013 D09006 4 D01038 D02004 R01000 D03013 D09007 4 D01037 D02004 R01000 D03014 D09008 4 D01038 D02004 R01000 D03014 D09011 3 D01039 R01000 D03011 D09012 3 D01039 R01000 D03012 D09013 4 D01039 D02004 R01000 D03013 D09014 4 D01039 D02004 R01000 D03014 D09015 3 D01040 R01000 D03011 D09016 3 D01040 R01000 D03012 D09017 4 D01040 D02004 R01000 D03013 D09018 4 D01040 D02004 R01000 D03014 D09019 4 D01031 B02003 R01000 D03011 D09020 7 D01031 B02003 R04000 B07003 B11003 B11004 B11005 D09030 7 B15004 B15005 R04000 B04015 B08006 B07004 B15003 D09040 3 D01075 D01076 D09030 D09041 4 D07041 D01075 D01076 D09030 D09042 4 D07042 D01075 D01076 D09030 D09044 4 D07044 D01075 D01076 D09030 D10001 5 D01042 D03031 D03032 R01026 D03025 D10002 5 D01042 D03031 D03032 R01009 D03023 D10003 5 D01042 D03031 D03032 R01006 D03023 D10004 5 D01042 D03031 D03032 R01003 D03024 D10005 5 D01042 D03031 D03033 R01000 D03025 D10006 5 D01042 D03031 D03033 R01000 D03023 D10007 5 D01042 D03031 D03033 R01000 D03024 D10008 8 D10011 R01019 D10012 B02150 B25079 B25080 B33032 B14045 D10009 3 D10011 R01015 D10012 D10010 3 D10011 R01005 D10012 D10014 3 D01072 D03041 D04011 D10015 13 D01072 B07024 B10002 D03041 R01003 D04032 B02152 B02024 B07004 B07004 B13003 R01003 D04033 D10016 13 D01072 B07024 B10002 D03041 R01012 D04032 B02152 B02024 B07004 B07004 B13003 R01012 D04033 D10020 6 D10022 D01011 D01013 D01021 D04034 D10021 D10022 4 B01007 B02019 B01033 B02172 D10023 17 D01072 B30021 B30022 B08012 B07024 B07025 B10002 R01012 D04032 R05002 B02152 B02024 B07004 B07004 B13003 R01012 D04033 D10050 13 D10051 D10052 R01000 D10053 R01004 D10054 B20010 D10052 R01015 D10053 D10052 R01004 D10053 D10195 3 D01250 D03250 D04250 D11001 9 D01051 B07002 B12001 B11001 B11002 B11031 B11032 B11033 B20041 D11002 4 D01065 D01066 D11003 D11004 D11003 5 B10070 B11001 B11002 B12001 B13002 D11004 12 R01000 B11034 R01000 B11035 R01000 B11075 R01000 B11076 R01000 B33025 R01000 B33026 D11005 13 B01008 B01023 D01021 D01011 D01013 B07010 B08009 B11001 B11002 B11031 B11036 B12101 B33025 D11006 6 B07010 B11001 B11002 B02064 B12101 B12103 D11193 16 D01197 D01011 D01012 D01023 B08004 B07004 B08021 B11001 B11002 B11031 B11034 B11035 B12001 B12003 B13003 B20041 D12001 2 D01043 D04001 D12002 2 D01043 D04002 D12003 2 D01042 D04003 D12004 2 D01042 D04004 D12005 2 D01042 B20014 D12006 2 D01044 D04005 D12007 2 D01042 D04006 D12010 6 B01007 B05040 B02021 B05041 B04001 B04043 D12014 8 D12010 D12011 R05056 D01023 B05042 B05052 D12012 D12013 D12016 3 D12010 D12011 D12015 D12018 3 D12010 D12011 D12017 D12020 11 D01047 D01048 B15015 B29002 B21076 R04012 B06030 R02012 B05030 B21075 B21066 D12021 6 D01047 R01003 D01049 B11012 B11011 B21067 D12022 15 D01047 B08022 B11012 B11050 B22070 B22026 D12041 B10050 B21068 B21071 B21072 B21073 D12042 B21062 B15011 D12023 7 D01047 R03003 B08022 B12061 B22050 B21069 B21085 D12024 11 D12020 B08060 B08022 B08060 B08022 B25014 B22101 B22097 B22098 B22099 B22100 D12025 11 D12019 B08060 B08022 B08060 B08022 B25014 B22101 B22097 B22098 B22099 B22100 D12026 19 D01046 D01011 D01013 D01023 D12031 R01004 D12030 B21110 D01023 D21027 B21111 D01023 D21027 B21112 D01023 D21027 B21113 D01023 D21027 D12027 9 D01047 R05009 D01023 B07021 B12061 B07021 B12061 B21085 B21070 D12031 8 B05034 B06034 B21109 B11081 B11082 B21101 B21102 B21103 D12032 4 B21120 B21121 B13055 B21122 D12033 4 B02104 B08022 B12063 B12065 D12042 6 B21077 B21078 B21079 B21080 B21081 B21082 D12045 21 B01007 B02019 B01096 B25061 B05040 D01011 D01013 D01021 B07002 B12180 B12181 B12182 B12183 B12184 B12185 B02174 B21086 B12186 B21087 B12187 B33043 D13009 3 B21001 R01000 B21001 D13010 3 B21036 R01000 B21036 D13031 4 B06002 B06012 R01000 B30001 D13032 4 B05002 B05012 R01000 D13031 D13041 9 B06002 R10000 R04000 B06012 R01000 B30001 B06012 R01000 B30001 D13042 4 B05002 B05012 R01000 D13041 D13043 11 B06002 B05002 B05012 R12000 R10000 R04000 B06012 R01000 B30001 R01000 B30001 D15001 5 B01011 D01011 D01012 D01023 D06001 D15002 5 B01011 D01011 D01012 D01023 D06004 D16001 10 D01011 B04004 D01023 B01021 B02041 B19001 B10051 B19002 B19003 B19004 D16002 15 B08021 B04001 B04002 B04003 B04004 B04005 B01033 B08021 B04001 B04002 B04003 B04004 B04005 B07002 B07002 D16003 10 R09000 B08011 B08007 R04000 B05002 B06002 B10002 B11002 B08007 B08011 D16004 11 R10000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B11031 B08007 B08011 D16005 9 R08000 B08005 B08007 B05002 B06002 B01026 B19001 B08007 B08005 D16006 12 R11000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B20011 B20012 B08007 B08011 D16007 10 R09000 B08011 B08007 R04000 B05002 B06002 B19005 B19006 B08007 B08011 D16008 11 R10000 B08001 B08007 B08023 R03000 B05002 B06002 B10002 B08023 B08007 B08001 D16009 11 R10000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B20041 B08007 B08011 D16010 8 R07000 B08011 B08007 B01022 B05002 B06002 B08007 B08011 D16011 17 R16000 B08011 B01022 B08007 R02000 B05002 B06002 B08021 B04001 B04002 B04003 B04004 B04005 B20090 B08021 B08007 B08011 D16020 5 B01023 B01025 B01027 D01011 D01012 D16021 23 D01023 B02041 B19001 B19007 B19005 B19006 B19008 B08005 B10004 B08005 B10004 B19007 B08005 B08021 B04075 B11040 B19007 R05004 B05021 B05021 R02002 B19003 B19004 D16022 23 B01032 B02041 B19001 B19010 R18000 B08021 B04014 B08005 D01023 B19005 B19006 B10004 B11041 B08021 B04075 B11040 B19008 R05004 B05021 B05021 R02002 B19003 B19004 D16026 2 D16020 D16021 D18001 2 D01025 B24011 D18003 4 D01026 B24005 B24004 B24021 D18004 6 D01025 B04023 B13011 B24005 B24004 B24022 D21001 6 B02101 B02114 B02105 B02106 B02107 B02121 D21003 4 B21051 B21014 B21017 B21030 D21004 4 D01031 B02003 R01000 D21003 D21005 12 B25004 B02121 B02122 B02123 B02124 B02125 B02126 B02127 B02128 B02129 B02130 B02131 D21006 4 B25001 B25002 B25003 B25005 D21007 8 B25009 B25010 B25011 B25012 B25013 B25015 B25016 B25017 D21008 3 B25006 B25007 B25008 D21009 2 B25018 B25019 D21010 13 B02101 B07002 B02102 B02103 B02104 B02105 B02106 B02107 B02108 B02109 B02110 B02132 B02133 D21011 3 B30031 B30032 B29002 D21012 2 R01000 B02135 D35001 4 B08035 B35001 B08036 D01001 D35002 4 B08035 B35001 B08036 B01033 D35003 6 B08021 B04001 B04002 B04003 B04004 B04073 D35004 7 B08021 B04004 B08021 B04004 B35000 D01001 B35011 D35005 7 B08021 B04004 B08021 B04004 B35000 B01001 B35011 D35006 7 B08021 B04004 B08021 B04004 B35000 B01003 B35011 D35007 9 B08021 B04004 B08021 B04004 B35000 B01001 R02000 B01002 B35011 D35010 3 D35002 D35003 D35007 dballe-7.7/tables/B0000000000200014001.txt0000644000175000017500000016761012652630120013567 00000000000000 001001 WMO BLOCK NUMBER NUMERIC 0 0 7 001002 WMO STATION NUMBER NUMERIC 0 0 10 001006 AIRCRAFT FLIGHT NUMBER CCITTIA5 0 0 64 001007 SATELLITE IDENTIFIER CODE TABLE 1007 0 0 10 001008 AIRCRAFT REGISTRATION NUMBER OR OTHER IDENTIFICATION CCITTIA5 0 0 64 001011 SHIP OR MOBILE LAND STATION IDENTIFIER CCITTIA5 0 0 72 001012 DIRECTION OF MOTION OF MOVING OBSERVING PLATFORM** DEGREE TRUE 0 0 9 001013 SPEED OF MOTION OF MOVING OBSERVING PLATFORM* M/S 0 0 10 001019 LONG STATION OR SITE NAME CCITTIA5 0 0 256 001023 OBSERVATION SEQUENCE NUMBER NUMERIC 0 0 9 001033 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE CODE TABLE 001033 0 0 8 001034 IDENTIFICATION OF ORIGINATING/GENERATING SUB-CENTRE CODE TABLE 001034 0 0 8 001063 ICAO LOCATION INDICATOR CCITTIA5 0 0 64 001192 [SIM] MeteoDB station ID NUMERIC 0 0 24 001193 [SIM] Report code NUMERIC 0 0 16 001194 [SIM] Report mnemonic CCITTIA5 0 0 128 001212 AIR QUALITY OBSERVING STATION LOCAL CODE CCITTIA5 0 0 56 001213 AIRBASE AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 56 001214 GEMS AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 48 001215 AIR QUALITY OBSERVING STATION DOMINANT EMISSION SOURCE CODE TABLE 001215 0 0 3 001216 AIR QUALITY OBSERVING STATION AREA TYPE CODE TABLE 001216 0 0 3 001217 AIR QUALITY OBSERVING STATION TERRAIN TYPE CODE TABLE 001217 0 0 4 002001 TYPE OF STATION CODE TABLE 2001 0 0 2 002002 TYPE OF INSTRUMENTATION FOR WIND MEASUREMENT FLAG TABLE 2002 0 0 4 002003 TYPE OF MEASURING EQUIPMENT USED CODE TABLE 2003 0 0 4 002004 TYPE OF INSTRUMENTATION FOR EVAPORATION MEASUREMENT OR TYPE OF C CODE TABLE 2004 0 0 4 002005 PRECISION OF TEMPERATURE OBSERVATION K 2 0 7 002011 RADIOSONDE TYPE CODE TABLE 2011 0 0 8 002012 RADIOSONDE COMPUTATIONAL METHOD CODE TABLE 2012 0 0 4 002013 SOLAR AND INFRARED RADIATION CORRECTION CODE TABLE 2013 0 0 4 002014 TRACKING TECHNIQUE/STATUS OF SYSTEM USED CODE TABLE 2014 0 0 7 002038 METHOD OF WATER TEMPERATURE AND/OR SALINITY MEASUREMENT CODE TABLE 2038 0 0 4 002039 METHOD OF WET-BULB TEMPERATURE MEASUREMENT CODE TABLE 2039 0 0 3 002048 SATELLITE SENSOR INDICATOR CODE TABLE 2048 0 0 4 002061 AIRCRAFT NAVIGATIONAL SYSTEM CODE TABLE 2061 0 0 3 002062 TYPE OF AIRCRAFT DATA RELAY SYSTEM CODE TABLE 2062 0 0 4 002063 AIRCRAFT ROLL ANGLE DEGREE 2 -18000 16 002064 AIRCRAFT ROLL ANGLE QUALITY CODE TABLE 2064 0 0 2 002070 ORIGINAL SPECIFICATION OF LATITUDE/LONGITUDE CODE TABLE 2070 0 0 4 002121 MEAN FREQUENCY Hz -8 0 7 002125 PULSE REPETITION FREQUENCY Hz -1 0 8 004001 YEAR YEAR 0 0 12 004002 MONTH MONTH 0 0 4 004003 DAY DAY 0 0 6 004004 HOUR HOUR 0 0 5 004005 MINUTE MINUTE 0 0 6 004006 SECOND SECOND 0 0 6 004086 LONG TIME PERIOD OR DISPLACEMENT SECOND 0 -8192 15 004192 [SIM] Time range type NUMERIC 0 0 10 004193 [SIM] Time range P1 NUMERIC 0 -536870912 31 004194 [SIM] Time range P2 NUMERIC 0 -536870912 31 004195 [SIM] Temperature event - time of occurrence MINUTE 0 0 11 004196 [SIM] Relative humidity event - time of occurrence MINUTE 0 0 11 004197 [SIM] Wind velocity event - time of occurrence MINUTE 0 0 11 004198 [SIM] Pressure event - time of occurrence MINUTE 0 0 11 005001 LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 005015 LATITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -9000000 25 005021 BEARING OR AZIMUTH DEGREE TRUE 2 0 16 005022 SOLAR AZIMUTH DEGREE TRUE 2 0 16 005040 ORBIT NUMBER NUMERIC 0 0 24 005041 SCAN LINE NUMBER NUMERIC 0 0 8 005043 FIELD OF VIEW NUMBER NUMERIC 0 0 8 006001 LONGITUDE (HIGH ACCURACY) DEGREE 5 -18000000 26 006015 LONGITUDE DISPLACEMENT (HIGH ACCURACY) DEGREE 5 -18000000 26 007002 HEIGHT OR ALTITUDE M -1 -40 16 007004 PRESSURE PA -1 0 14 007007 HEIGHT M 0 -1000 17 007010 FLIGHT LEVEL M 0 -1024 16 007024 SATELLITE ZENITH ANGLE DEGREE 2 -9000 15 007025 SOLAR ZENITH ANGLE DEGREE 2 -9000 15 007030 HEIGHT OF STATION GROUND ABOVE MEAN SEA LEVEL (SEE NOTE 3) M 1 -4000 17 007031 HEIGHT OF BAROMETER ABOVE MEAN SEA LEVEL (SEE NOTE 4) M 1 - 4000 17 007032 HEIGHT OF SENSOR ABOVE LOCAL GROUND (OR DECK OF MARINE PLATFORM) M 2 0 16 007192 [SIM] First level type NUMERIC 0 0 10 007193 [SIM] Level L1 NUMERIC 0 -536870912 31 007194 [SIM] Level L2 NUMERIC 0 -536870912 31 007195 [SIM] Second level type NUMERIC 0 0 31 008002 VERTICAL SIGNIFICANCE (SURFACE OBSERVATIONS) CODE TABLE 8002 0 0 6 008004 PHASE OF AIRCRAFT FLIGHT CODE TABLE 8004 0 0 3 008009 DETAILED PHASE OF FLIGHT CODE TABLE 8009 0 0 4 008021 TIME SIGNIFICANCE CODE TABLE 8021 0 0 5 008042 EXTENDED VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8042 0 0 18 008044 (VAL) CAS REGISTRY NUMBER CCITTIA5 0 0 88 008192 [SIM] Number of wind velocity mean values present NUMERIC 0 0 5 008193 [SIM] Number of wind velocity minimum values present NUMERIC 0 0 5 008194 [SIM] Number of wind velocity maximum values present NUMERIC 0 0 5 008195 [SIM] Number of wind prevalent direction values present NUMERIC 0 0 5 008196 [SIM] Number of mean temperature values present NUMERIC 0 0 5 008197 [SIM] Number of minimum temperature values present NUMERIC 0 0 5 008198 [SIM] Number of maximum temperature values present NUMERIC 0 0 5 008199 [SIM] Number of mean relative humidity values present NUMERIC 0 0 5 008200 [SIM] Number of minimum relative humidity values present NUMERIC 0 0 5 008201 [SIM] Number of maximum relative humidity values present NUMERIC 0 0 5 008202 [SIM] Number of mean pressure values present NUMERIC 0 0 5 008203 [SIM] Number of minimum pressure values present NUMERIC 0 0 5 008204 [SIM] Number of maximum pressure values present NUMERIC 0 0 5 008205 [SIM] Number of precipitation values present NUMERIC 0 0 5 008206 [SIM] Number of leaf wetness values present NUMERIC 0 0 5 008207 [SIM] Number of scalar wind velocity mean values present NUMERIC 0 0 5 008208 [SIM] Number of cloud cover mean values present NUMERIC 0 0 5 008209 [SIM] Number of cloud cover maximum values present NUMERIC 0 0 5 008210 [SIM] Number of cloud cover minimum values present NUMERIC 0 0 5 010004 PRESSURE PA -1 0 14 010007 HEIGHT M 0 -1000 17 010008 GEOPOTENTIAL M**2/S**2 0 -10000 20 010009 GEOPOTENTIAL HEIGHT GPM 0 -1000 17 010051 PRESSURE REDUCED TO MEAN SEA LEVEL PA -1 0 14 010052 ALTIMETER SETTING (QNH) PA -1 0 14 010060 PRESSURE CHANGE PA -1 -1024 11 010063 CHARACTERISTIC OF PRESSURE TENDENCY CODE TABLE 10063 0 0 4 010197 ANEMOMETER HEIGHT M 0 0 9 011001 WIND DIRECTION DEGREE TRUE 0 0 9 011002 WIND SPEED M/S 1 0 12 011003 U-COMPONENT M/S 1 -4096 13 011004 V-COMPONENT M/S 1 -4096 13 011005 W-COMPONENT PA/S 1 -512 10 011006 W-COMPONENT M/S 2 -4096 13 011016 EXTREME COUNTERCLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 011017 EXTREME CLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 011031 DEGREE OF TURBULENCE CODE TABLE 11031 0 0 4 011036 MAXIMUM DERIVED EQUIVALENT VERTICAL GUST SPEED M/S 1 0 10 011037 TURBULENCE INDEX CODE TABLE 11037 0 0 6 011039 EXTENDED TIME OF OCCURRENCE OF PEAK EDDY DISSIPATION RATE CODE TABLE 11039 0 0 6 011041 MAXIMUM WIND GUST SPEED M/S 1 0 12 011043 MAXIMUM WIND GUST DIRECTION DEGREE TRUE 0 0 9 011050 STANDARD DEVIATION OF HORIZONTAL WIND SPEED M/S 1 0 12 011061 ABSOLUTE WIND SHEAR IN 1 KM LAYER BELOW M/S 1 0 12 011062 ABSOLUTE WIND SHEAR IN 1 KM LAYER ABOVE M/S 1 0 12 011075 MEAN TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 011076 PEAK TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 011077 REPORTING INTERVAL OR AVERAGING TIME FOR EDDY DISSIPATION RATE S 0 0 12 011192 [SIM] W-component terrain following M/S 2 -4096 13 011193 [SIM] Stability class NUMERIC 0 0 4 011194 [SIM] Friction velocity (calmet) M/S 3 0 14 011195 [SIM] Mixing height (calmet) M 0 0 12 011196 [SIM] Obukov lenght (calmet) M 1 -100000 15 011197 [SIM] Convective velocitiy scale (calmet) M/S 3 0 14 011198 [SIM] SQRT(2*TKE) M/S 4 0 20 011199 [SIM] Surface Roughness M 3 0 14 011200 [SIM] U-component of momentum flux N/M**2 4 -524288 20 011201 [SIM] V-component of momentum flux N/M**2 4 -524288 20 011202 [SIM] Friction velocity (diagmet) M/S 3 0 14 011203 [SIM] Mixing height (diagmet) M 0 0 12 011204 [SIM] Obukov lenght (diagmet) M 1 -100000 15 011205 [SIM] Convective velocitiy scale (diagmet) M/S 3 0 14 011206 [SIM] Friction velocity (COSMO) M/S 3 0 14 011207 [SIM] Obukov lenght (COSMO) M 1 -100000 15 011208 [SIM] Distance covered by the hourly mean wind M 0 0 23 012001 TEMPERATURE/AIR TEMPERATURE K 1 0 12 012003 DEW-POINT TEMPERATURE K 1 0 12 012030 SOIL TEMPERATURE K 1 0 12 012049 Temperature change over specified period K 0 -30 6 012061 SKIN TEMPERATURE K 1 0 12 012063 BRIGHTNESS TEMPERATURE K 1 0 12 012101 TEMPERATURE/DRY-BULB TEMPERATURE K 2 0 16 012102 WET-BULB TEMPERATURE K 2 0 16 012103 DEW-POINT TEMPERATURE K 2 0 16 012121 GROUND MINIMUM TEMPERATURE K 2 0 16 012131 SNOW TEMPERATURE K 2 0 16 012192 POTENTIAL TEMPERATURE K 2 0 16 012193 PSEUDO-EQUIVALENT POTENTIAL TEMPERATURE K 2 0 16 012194 [SIM] Air density KG/M**3 6 0 20 013001 SPECIFIC HUMIDITY KG/KG 5 0 14 013002 MIXING RATIO KG/KG 5 0 14 013003 RELATIVE HUMIDITY % 0 0 7 013011 TOTAL PRECIPITATION / TOTAL WATER EQUIVALENT KG/M**2 1 -1 14 013012 DEPTH OF FRESH SNOW M 2 -2 12 013013 TOTAL SNOW DEPTH M 3 -20 20 013031 EVAPOTRANSPIRATION KG/M**2 1 0 7 013033 EVAPORATION/EVAPOTRANSPIRATION KG/M**2 1 0 10 013081 WATER CONDUCTIVITY S/M 3 0 14 013082 WATER TEMPERATURE K 1 0 12 013192 [SIM] Cloud liquid water content KG/KG 8 0 27 013193 [SIM] Cloud ice content KG/KG 8 0 27 013194 [SIM] Water table depth M 3 0 18 013195 [SIM] Precipitating liquid water KG/KG 8 0 27 013196 [SIM] Precipitating ice KG/KG 8 0 27 013197 [SIM] Total precipitating water+ice KG/KG 8 0 27 013198 [SIM] Total liquid water (cloud+precipitating) KG/KG 8 0 27 013199 [SIM] Total ice (cloud+precipitating) KG/KG 8 0 27 013200 [SIM] Grid-scale liquid precipitation KG/M**2 1 -1 14 013201 [SIM] Grid-scale snowfall KG/M**2 1 -1 14 013202 [SIM] Convective liquid precipitation KG/M**2 1 -1 14 013203 [SIM] Convective snowfall KG/M**2 1 -1 14 013204 [SIM] Total convective precipitation (liquid + snow) KG/M**2 1 -1 14 013205 [SIM] Snowfall (grid-scale + convective) KG/M**2 1 -1 14 013206 [SIM] Soil water content KG/M**2 1 0 14 013210 [SIM] Penetration of the probe in the snow M 2 0 9 013212 [SIM] Leaf wetness duration S -1 0 24 013215 [SIM] River level M 2 -100000 18 013216 [SIM] Hourly precipitation KG/M**2 1 -1 14 013217 [SIM] 5 minutes precipitation KG/M**2 1 -1 14 013218 [SIM] 10 minutes precipitation KG/M**2 1 -1 14 013219 [SIM] 15 minutes precipitation KG/M**2 1 -1 14 013220 [SIM] 20 minutes precipitation KG/M**2 1 -1 14 013221 [SIM] 30 minutes precipitation KG/M**2 1 -1 14 013222 [SIM] 180 minutes precipitation KG/M**2 1 -1 14 013223 [SIM] 360 minutes precipitation KG/M**2 1 -1 14 013224 [SIM] 720 minutes precipitation KG/M**2 1 -1 14 013225 [SIM] 1440 minutes precipitation KG/M**2 1 -1 14 013226 [SIM] River discharge M**3/S 2 0 21 013227 [SIM] Soil volumetric water content % 1 0 10 013228 [SIM] Piezometric level M 3 0 18 013229 [SIM] Density of snow KG/M**3 1 0 14 013230 [SIM] Convective Available Potential Energy (CAPE) J/KG 1 0 17 014002 Long-wave radiation, integrated over period specified J M-2 -3 -65536 17 014004 Short-wave radiation, integrated over period specified J M-2 -3 -65536 17 014016 NET RADIATION J/M**2 -4 -16384 15 014017 INSTANTANEOUS LONG-WAVE RADIATION (incoming) W/M**2 0 -2048 12 014018 INSTANTANEOUS SHORT-WAVE RADIATION (incoming) W/M**2 0 -2048 12 014019 SURFACE ALBEDO % 0 0 7 014021 GLOBAL SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 014028 Global solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 014029 Diffuse solar radiation (high accuracy), integrated over period J M-2 -2 0 20 014030 Direct solar radiation (high accuracy), integrated over period s J M-2 -2 0 20 014031 TOTAL SUNSHINE MINUTE 0 0 11 014192 [SIM] Instantenous sensible heat flux W/m**2 0 -1024 11 014193 [SIM] Instantenous latent heat flux W/m**2 0 -1024 11 014194 [SIM] Instantenous direct solar radiation W/M**2 0 -2048 12 014195 [SIM] Instantenous diffuse solar radiation W/M**2 0 -2048 12 014196 [SIM] INSTANTANEOUS NET LONG-WAVE RADIATION W/M**2 0 -2048 12 014197 [SIM] INSTANTANEOUS NET SHORT-WAVE RADIATION W/M**2 0 -2048 12 014198 [SIM] Visible radiation (downward) W/M**2 3 -50000 21 014199 [SIM] Visible radiation (upward) W/M**2 3 -50000 21 014200 [SIM] Infrared radiation (downward) W/M**2 3 0 20 014201 [SIM] Infrared radiation (upward) W/M**2 3 0 20 015192 [SIM] NO Concentration KG/M**3 10 0 20 015193 [SIM] NO2 Concentration KG/M**3 10 0 20 015194 [SIM] O3 Concentration KG/M**3 10 0 20 015195 [SIM] PM10 Concentration KG/M**3 10 0 20 015196 [SIM] CO Concentration KG/M**3 10 0 20 015197 [SIM] SO2 Concentration KG/M**3 10 0 20 015198 [SIM] PM2.5 Concentration KG/M**3 10 0 20 015199 [SIM] NOY Concentration KG/M**3 10 0 20 015200 [SIM] HCNM Concentration KG/M**3 10 0 20 015201 [SIM] ALDE Concentration KG/M**3 10 0 20 015202 [SIM] PM5 Concentration (tot. aerosol < 5 ug) KG/M**3 10 0 20 015203 [SIM] PM1 Concentration (tot. aerosol < 1.25 ug) KG/M**3 10 0 20 015204 [SIM] PM06 Concentration (tot. aerosol < 0.6 ug) KG/M**3 10 0 20 015205 [SIM] PM03 Concentration (tot. aerosol < 0.3 ug) KG/M**3 10 0 20 015206 [SIM] PM015 Concentration (tot. aerosol < 0.15 ug) KG/M**3 10 0 20 015207 [SIM] PM008 Concentration (tot. aerosol < 0.08 ug) KG/M**3 10 0 20 015208 [SIM] Concentration of primary particulate matter in PM10 KG/M**3 10 0 20 015209 [SIM] Concentration of sulfate in PM10 KG/M**3 10 0 20 015210 [SIM] Concentration of nitrate in PM10 KG/M**3 10 0 20 015211 [SIM] Concentration of ammonium in PM10 KG/M**3 10 0 20 015212 [SIM] Concentration of black carbon in PM10 KG/M**3 10 0 20 015213 [SIM] Concentration of organic carbon in PM10 KG/M**3 10 0 20 015214 [SIM] Concentration of dust in PM10 KG/M**3 10 0 20 015215 [SIM] Concentration of anthrop. A1D in PM10 KG/M**3 10 0 20 015216 [SIM] Concentration of anthrop. BmP in PM10 KG/M**3 10 0 20 015217 [SIM] Concentration of biogenic A1D in PM10 KG/M**3 10 0 20 015218 [SIM] Concentration of biogenic BmP in PM10 KG/M**3 10 0 20 015219 [SIM] Concentration of water in PM10 KG/M**3 10 0 20 015220 [SIM] Concentration of sea salt in PM10 KG/M**3 10 0 20 015221 [SIM] Concentration of secondary organic aerosol in PM10 KG/M**3 10 0 20 015222 [SIM] Total concentration of primary aerosol in PM10 KG/M**3 10 0 20 015223 [SIM] Total concentration of secondary aerosol in PM10 KG/M**3 10 0 20 015224 [SIM] Uncertainity in O3 estimate (Pesco) KG/M**3 10 0 20 015225 [SIM] Uncertainity in PM10 estimate (Pesco) KG/M**3 10 0 20 015226 [SIM] Uncertainity in NO2 estimate (Pesco) KG/M**3 10 0 20 015227 [SIM] Uncertainity in PM2.5 estimate (Pesco) KG/M**3 10 0 20 015228 [SIM] NH3 Concentration KG/M**3 10 0 20 015229 [SIM] Concentration of primary part. matter in aerosol KG/M**3 10 0 20 015230 [SIM] Concentration of sulfate in aerosol KG/M**3 10 0 20 015231 [SIM] Concentration of nitrate in aerosol KG/M**3 10 0 20 015232 [SIM] Concentration of ammonium in aerosol KG/M**3 10 0 20 015233 [SIM] Concentration of anthrop. sec. org. in aerosol KG/M**3 10 0 20 015234 [SIM] Concentration of biogenic sec. org. in aerosol KG/M**3 10 0 20 015235 [SIM] Concentration of ISOPA1 in PM10 KG/M**3 10 0 20 015236 [SIM] C6H6 Concentration KG/M**3 10 0 20 015237 [SIM] Concentration of anthropogenic aerosol in PM10 KG/M**3 10 0 20 015238 [SIM] Concentration of biogenic aerosol in PM10 KG/M**3 10 0 20 015239 [SIM] Concentration of anthropogenic aerosol in PM2.5 KG/M**3 10 0 20 015240 [SIM] Concentration of biogenic aerosol in PM2.5 KG/M**3 10 0 20 015241 [SIM] Aerosol Optical Thickness NUMERIC 4 0 15 020001 HORIZONTAL VISIBILITY M -1 0 13 020003 PRESENT WEATHER (SEE NOTE 1) CODE TABLE 20003 0 0 9 020004 PAST WEATHER (1) (SEE NOTE 2) CODE TABLE 20004 0 0 5 020005 PAST WEATHER (2) (SEE NOTE 2) CODE TABLE 20005 0 0 5 020009 GENERAL WEATHER INDICATOR (TAF/METAR) CODE TABLE 20009 0 0 4 020010 CLOUD COVER (TOTAL) % 0 0 7 020011 CLOUD AMOUNT CODE TABLE 20011 0 0 4 020012 CLOUD TYPE CODE TABLE 20012 0 0 6 020013 HEIGHT OF BASE OF CLOUD M 0 -400 17 020017 CLOUD TOP DESCRIPTION CODE TABLE 20017 0 0 4 020019 SIGNIFICANT PRESENT OR FORECAST WEATHER CCITTIA5 0 0 72 020021 TYPE OF PRECIPITATION FLAG TABLE 20021 0 0 30 020031 ICE DEPOSIT (THICKNESS) M 2 0 7 020032 RATE OF ICE ACCRETION CODE TABLE 20032 0 0 3 020033 CAUSE OF ICE ACCRETION FLAG TABLE 20033 0 0 4 020034 SEA ICE CONCENTRATION CODE TABLE 20034 0 0 5 020035 AMOUNT AND TYPE OF ICE CODE TABLE 20035 0 0 4 020036 ICE SITUATION CODE TABLE 20036 0 0 5 020037 ICE DEVELOPMENT CODE TABLE 20037 0 0 5 020038 BEARING OF ICE EDGE (SEE NOTE 3) DEGREE TRUE 0 0 12 020042 AIRFRAME ICING PRESENT CODE TABLE 20042 0 0 2 020043 PEAK LIQUID WATER CONTENT KG/M**3 4 0 7 020044 AVERAGE LIQUID WATER CONTENT KG/M**3 4 0 7 020045 SUPERCOOLED LARGE DROPLET (SLD) CONDITIONS CODE TABLE 20045 0 0 2 020062 STATE OF THE GROUND (WITH OR WITHOUT SNOW) CODE TABLE 20062 0 0 5 020192 [SIM] Presence of rain > 1mm BOOLEAN 0 0 1 020193 [SIM] Cloud type (METAR) CCITTIA5 0 0 16 020194 [SIM] Presence of shower BOOLEAN 0 0 1 020195 [SIM] Presence of hail BOOLEAN 0 0 1 020196 [SIM] Presence of thunderstorm BOOLEAN 0 0 1 020197 [SIM] Presence of snow BOOLEAN 0 0 1 020198 [SIM] Presence of frost BOOLEAN 0 0 1 020199 [SIM] Presence of dew BOOLEAN 0 0 1 020200 [SIM] Presence of fog BOOLEAN 0 0 1 020201 [SIM] Presence of water-spout BOOLEAN 0 0 1 020202 [SIM] State of the ground with snow CODE TABLE 0 0 5 022001 DIRECTION OF WAVES DEGREE TRUE 0 0 9 022002 DIRECTION OF WIND WAVES DEGREE TRUE 0 0 9 022003 DIRECTION OF SWELL WAVES DEGREE TRUE 0 0 9 022004 DIRECTION OF CURRENT DEGREE TRUE 0 0 9 022011 PERIOD OF WAVES S 0 0 6 022012 PERIOD OF WIND WAVES S 0 0 6 022013 PERIOD OF SWELL WAVES S 0 0 6 022021 HEIGHT OF WAVES M 1 0 10 022022 HEIGHT OF WIND WAVES M 1 0 10 022023 HEIGHT OF SWELL WAVES M 1 0 10 022031 SPEED OF CURRENT M/S 2 0 13 022032 SPEED OF SEA SURFACE CURRENT M/S 2 0 13 022037 Tidal elevation with respect to national land datum M 3 -10000 15 022038 Tidal elevation with respect to local chart datum M 3 -10000 15 022042 SEA/WATER TEMPERATURE K 1 0 12 022043 SEA/WATER TEMPERATURE K 2 0 15 022049 SEA-SURFACE TEMPERATURE K 2 0 15 022070 SIGNIFICANT WAVE HEIGHT M 2 0 13 022071 SPECTRAL PEAK WAVE PERIOD S 1 0 9 022074 AVERAGE WAVE PERIOD S 1 0 9 022192 [SIM] Current X component M/S 2 0 13 022193 [SIM] Current Y component M/S 2 0 13 023192 [SIM] Dry deposition of H2SO4 MOL/M**2 5 0 20 023193 [SIM] Wet deposition of H2SO4 MOL/M**2 5 0 20 023194 [SIM] Dry deposition of NH4 MOL/M**2 5 0 20 023195 [SIM] Wet deposition of NH4 MOL/M**2 5 0 20 023196 [SIM] Dry deposition of HNO3 MOL/M**2 5 0 20 023197 [SIM] Wet deposition of HNO3 MOL/M**2 5 0 20 023198 [SIM] Solid transport by river KG/S 2 0 24 025076 LOG-10 OF (TEMP-RAD CENTRAL WAVENUMBER) FOR ATOVS LOGM-1 8 0 30 029192 [SIM] Land fraction % 1 0 10 031000 SHORT DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 1 031001 DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 8 031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 16 031011 DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 8 031012 EXTENDED DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 16 031021 ASSOCIATED FIELD SIGNIFICANCE CODE TABLE 31021 0 0 6 031031 DATA PRESENT INDICATOR FLAG TABLE 31031 0 0 1 033002 QUALITY INFORMATION CODE TABLE 33002 0 0 2 033003 QUALITY INFORMATION CODE TABLE 33003 0 0 3 033005 QUALITY INFORMATION (AWS DATA) FLAG TABLE 33005 0 0 30 033006 INTERNAL MEASUREMENT STATUS INFORMATION (AWS) CODE TABLE 33006 0 0 3 033007 PER CENT CONFIDENCE % 0 0 7 033015 DATA QUALITY CHECK INDICATOR CODE TABLE 33015 0 0 6 033020 QUALITY CONTROL INDICATION OF FOLLOWING VALUE CODE TABLE 33020 0 0 3 033021 QUALITY OF FOLLOWING VALUE CODE TABLE 33021 0 0 2 033022 QUALITY OF BUOY SATELLITE TRANSMISSION CODE TABLE 33022 0 0 2 033023 QUALITY OF BUOY LOCATION CODE TABLE 33023 0 0 2 033024 STATION ELEVATION QUALITY MARK (FOR MOBILE STATIONS) CODE TABLE 33024 0 0 4 033025 ACARS INTERPOLATED VALUES CODE TABLE 33025 0 0 3 033026 MOISTURE QUALITY CODE TABLE 33026 0 0 6 033027 LOCATION QUALITY CLASS (RANGE OF RADIUS OF 66 % CONFIDENCE) CODE TABLE 33027 0 0 3 033030 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 33030 0 0 24 033031 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 33031 0 0 24 033032 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 33032 0 0 24 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS FLAG TABLE 33033 0 0 24 033035 MANUAL/AUTOMATIC QUALITY CONTROL CODE TABLE 33035 0 0 4 033036 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 033037 WIND CORRELATION ERROR FLAG TABLE 33037 0 0 20 033038 QUALITY FLAGS FOR GROUND-BASED GNSS DATA FLAG TABLE 33038 0 0 10 033040 CONFIDENCE INTERVAL % 0 0 7 033041 ATTRIBUTE OF FOLLOWING VALUE CODE TABLE 33041 0 0 2 033050 GLOBAL GTSPP QUALITY FLAG CODE TABLE 33050 0 0 4 033192 [SIM] Climatological and consistency check % 0 0 7 033193 [SIM] Time consistency % 0 0 7 033194 [SIM] Space consistency % 0 0 7 033195 [SIM] MeteoDB variable ID NUMERIC 0 0 24 033196 [SIM] Data has been invalidated CODE TABLE 33196 0 0 2 033197 [SIM] Manual replacement in substitution CODE TABLE 33197 0 0 2 033198 [SIM] Observation increment NUMERIC 4 -1073741823 31 033201 [SIM] Kalman coefficient, state vector (s.v.) x1 NUMERIC 4 -1073741823 31 033202 [SIM] Kalman coefficient, state vector (s.v.) x2 NUMERIC 4 -1073741823 31 033203 [SIM] Kalman coefficient, s.v. error covariance matrix(1,1) NUMERIC 4 -1073741823 31 033204 [SIM] Kalman coefficient, s.v. error covariance matrix(1,2) NUMERIC 4 -1073741823 31 033205 [SIM] Kalman coefficient, s.v. error covariance matrix(2,1) NUMERIC 4 -1073741823 31 033206 [SIM] Kalman coefficient, s.v. error covariance matrix(2,2) NUMERIC 4 -1073741823 31 033207 [SIM] Kalman observation sequential counter NUMERIC 0 -127 8 033208 [SIM] Kalman osservation missing counter NUMERIC 0 -127 8 033209 [SIM] Normalized Density Index % 0 0 7 048001 [SIM] Graminacee_Graminacee indistinte POLLEN/M**3 1 0 24 048002 [SIM] Betulacee_Ontano nero POLLEN/M**3 1 0 24 048003 [SIM] Betulacee_Betulla POLLEN/M**3 1 0 24 048004 [SIM] Betulacee_Betulacee indistinte POLLEN/M**3 1 0 24 048005 [SIM] Composite_Ambrosia POLLEN/M**3 1 0 24 048006 [SIM] Composite_Artemisia POLLEN/M**3 1 0 24 048007 [SIM] Composite_Composite indistinte POLLEN/M**3 1 0 24 048008 [SIM] Corilacee_Nocciolo POLLEN/M**3 1 0 24 048009 [SIM] Corilacee_Carpino bianco -Carpino nero POLLEN/M**3 1 0 24 048010 [SIM] Corilacee_Corilacee indistinte POLLEN/M**3 1 0 24 048011 [SIM] Fagacee_Castagno POLLEN/M**3 1 0 24 048012 [SIM] Fagacee_Faggio POLLEN/M**3 1 0 24 048013 [SIM] Fagacee_Quercia POLLEN/M**3 1 0 24 048014 [SIM] Fagacee_Fagacee indistinte POLLEN/M**3 1 0 24 048015 [SIM] Oleacee_Olivo POLLEN/M**3 1 0 24 048016 [SIM] Oleacee_Frassino POLLEN/M**3 1 0 24 048017 [SIM] Oleacee_Oleacee indistinte POLLEN/M**3 1 0 24 048018 [SIM] Plantaginacee_Plantaginacee indistinte POLLEN/M**3 1 0 24 048019 [SIM] Urticacee_Urticacee indistinte POLLEN/M**3 1 0 24 048020 [SIM] Cupressacee - Taxacee indistinte_Cipresso comune POLLEN/M**3 1 0 24 048021 [SIM] Cupressacee - Taxacee indistinte_Cupressacee - Taxacee ind POLLEN/M**3 1 0 24 048022 [SIM] Chenopodiacee - Amarantacee Indistinte_Amaranto POLLEN/M**3 1 0 24 048023 [SIM] Chenopodiacee - Amarantacee Indistinte_Chenopodiacee - Ama POLLEN/M**3 1 0 24 048024 [SIM] Poligonacee_Poligonacee indistinte POLLEN/M**3 1 0 24 048025 [SIM] Euphorbiacee_Euforbiacee indistinte POLLEN/M**3 1 0 24 048026 [SIM] Mirtacee_Mirtacee indistinte POLLEN/M**3 1 0 24 048027 [SIM] Ulmacee_Bagolaro comune POLLEN/M**3 1 0 24 048028 [SIM] Ulmacee_Olmo campestre POLLEN/M**3 1 0 24 048029 [SIM] Ulmacee_Ulmacee indistinte POLLEN/M**3 1 0 24 048030 [SIM] Platanacee_Platanacee indistinte POLLEN/M**3 1 0 24 048031 [SIM] Aceraceae_Aceracee indistinte POLLEN/M**3 1 0 24 048032 [SIM] Pinacee_Pinacee indistinte POLLEN/M**3 1 0 24 048033 [SIM] Salicacee_Salice comune POLLEN/M**3 1 0 24 048034 [SIM] Salicacee_Pioppo POLLEN/M**3 1 0 24 048035 [SIM] Salicacee_Salicacee indistinte POLLEN/M**3 1 0 24 048036 [SIM] Ciperacee_Ciperacee indistinte POLLEN/M**3 1 0 24 048037 [SIM] Juglandacee_Juglandacee indistinte POLLEN/M**3 1 0 24 048038 [SIM] Ippocastanacee_Ippocastanacee indistinte POLLEN/M**3 1 0 24 048039 [SIM] Spore fungine_Alternaria POLLEN/M**3 1 0 24 048040 [SIM] Spore fungine_Botrytis POLLEN/M**3 1 0 24 048041 [SIM] Spore fungine_Stemphylium POLLEN/M**3 1 0 24 048042 [SIM] Spore fungine_Cladosporium POLLEN/M**3 1 0 24 048043 [SIM] Spore fungine_Epicoccum POLLEN/M**3 1 0 24 048044 [SIM] Altri Pollini / Non Identificati_Altri pollini identificat POLLEN/M**3 1 0 24 048045 [SIM] Altri Pollini / Non Identificati_Pollini non identificati POLLEN/M**3 1 0 24 048046 [SIM] Altre Spore / Non identificati_Altre spore fungine POLLEN/M**3 1 0 24 048047 [SIM] Altre Spore / Non identificati_Spore fungine non identific POLLEN/M**3 1 0 24 048048 [SIM] Graminacee_Graminacee indistinte 1 POLLEN/M**3 1 0 24 048049 [SIM] Plantaginacee_Plantaginacee indistinte 1 POLLEN/M**3 1 0 24 048050 [SIM] Urticacee_Urticacee indistinte 1 POLLEN/M**3 1 0 24 048051 [SIM] Poligonacee_Poligonacee indistinte 1 POLLEN/M**3 1 0 24 048052 [SIM] Euphorbiacee_Euforbiacee indistinte 1 POLLEN/M**3 1 0 24 048053 [SIM] Mirtacee_Mirtacee indistinte 1 POLLEN/M**3 1 0 24 048054 [SIM] Platanacee_Platanacee indistinte 1 POLLEN/M**3 1 0 24 048055 [SIM] Aceraceae_Aceracee indistinte 1 POLLEN/M**3 1 0 24 048056 [SIM] Pinacee_Pinacee indistinte 1 POLLEN/M**3 1 0 24 048057 [SIM] Ciperacee_Ciperacee indistinte 1 POLLEN/M**3 1 0 24 048058 [SIM] Juglandacee_Juglandacee indistinte 1 POLLEN/M**3 1 0 24 048059 [SIM] Ippocastanacee_Ippocastanacee indistinte 1 POLLEN/M**3 1 0 24 048060 [SIM] Oleacee_Ligustro POLLEN/M**3 1 0 24 048128 [SIM] Conta Graminacee_Graminacee indistinte NUMERIC 0 0 20 048129 [SIM] Conta Betulacee_Ontano nero NUMERIC 0 0 20 048130 [SIM] Conta Betulacee_Betulla NUMERIC 0 0 20 048131 [SIM] Conta Betulacee_Betulacee indistinte NUMERIC 0 0 20 048132 [SIM] Conta Composite_Ambrosia NUMERIC 0 0 20 048133 [SIM] Conta Composite_Artemisia NUMERIC 0 0 20 048134 [SIM] Conta Composite_Composite indistinte NUMERIC 0 0 20 048135 [SIM] Conta Corilacee_Nocciolo NUMERIC 0 0 20 048136 [SIM] Conta Corilacee_Carpino bianco -Carpino nero NUMERIC 0 0 20 048137 [SIM] Conta Corilacee_Corilacee indistinte NUMERIC 0 0 20 048138 [SIM] Conta Fagacee_Castagno NUMERIC 0 0 20 048139 [SIM] Conta Fagacee_Faggio NUMERIC 0 0 20 048140 [SIM] Conta Fagacee_Quercia NUMERIC 0 0 20 048141 [SIM] Conta Fagacee_Fagacee indistinte NUMERIC 0 0 20 048142 [SIM] Conta Oleacee_Olivo NUMERIC 0 0 20 048143 [SIM] Conta Oleacee_Frassino NUMERIC 0 0 20 048144 [SIM] Conta Oleacee_Oleacee indistinte NUMERIC 0 0 20 048145 [SIM] Conta Plantaginacee_Plantaginacee indistinte NUMERIC 0 0 20 048146 [SIM] Conta Urticacee_Urticacee indistinte NUMERIC 0 0 20 048147 [SIM] Conta Cupressacee - Taxacee indistinte_Cipresso comune NUMERIC 0 0 20 048148 [SIM] Conta Cupressacee - Taxacee indistinte_Cupressacee - Taxac NUMERIC 0 0 20 048149 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Amaranto NUMERIC 0 0 20 048150 [SIM] Conta Chenopodiacee - Amarantacee Indistinte_Chenopodiacee NUMERIC 0 0 20 048151 [SIM] Conta Poligonacee_Poligonacee indistinte NUMERIC 0 0 20 048152 [SIM] Conta Euphorbiacee_Euforbiacee indistinte NUMERIC 0 0 20 048153 [SIM] Conta Mirtacee_Mirtacee indistinte NUMERIC 0 0 20 048154 [SIM] Conta Ulmacee_Bagolaro comune NUMERIC 0 0 20 048155 [SIM] Conta Ulmacee_Olmo campestre NUMERIC 0 0 20 048156 [SIM] Conta Ulmacee_Ulmacee indistinte NUMERIC 0 0 20 048157 [SIM] Conta Platanacee_Platanacee indistinte NUMERIC 0 0 20 048158 [SIM] Conta Aceraceae_Aceracee indistinte NUMERIC 0 0 20 048159 [SIM] Conta Pinacee_Pinacee indistinte NUMERIC 0 0 20 048160 [SIM] Conta Salicacee_Salice comune NUMERIC 0 0 20 048161 [SIM] Conta Salicacee_Pioppo NUMERIC 0 0 20 048162 [SIM] Conta Salicacee_Salicacee indistinte NUMERIC 0 0 20 048163 [SIM] Conta Ciperacee_Ciperacee indistinte NUMERIC 0 0 20 048164 [SIM] Conta Juglandacee_Juglandacee indistinte NUMERIC 0 0 20 048165 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte NUMERIC 0 0 20 048166 [SIM] Conta Spore fungine_Alternaria NUMERIC 0 0 20 048167 [SIM] Conta Spore fungine_Botrytis NUMERIC 0 0 20 048168 [SIM] Conta Spore fungine_Stemphylium NUMERIC 0 0 20 048169 [SIM] Conta Spore fungine_Cladosporium NUMERIC 0 0 20 048170 [SIM] Conta Spore fungine_Epicoccum NUMERIC 0 0 20 048171 [SIM] Conta Altri Pollini / Non Identificati_Altri pollini ident NUMERIC 0 0 20 048172 [SIM] Conta Altri Pollini / Non Identificati_Pollini non identif NUMERIC 0 0 20 048173 [SIM] Conta Altre Spore / Non identificati_Altre spore fungine NUMERIC 0 0 20 048174 [SIM] Conta Altre Spore / Non identificati_Spore fungine non ide NUMERIC 0 0 20 048175 [SIM] Conta Graminacee_Graminacee indistinte 1 NUMERIC 0 0 20 048176 [SIM] Conta Plantaginacee_Plantaginacee indistinte 1 NUMERIC 0 0 20 048177 [SIM] Conta Urticacee_Urticacee indistinte 1 NUMERIC 0 0 20 048178 [SIM] Conta Poligonacee_Poligonacee indistinte 1 NUMERIC 0 0 20 048179 [SIM] Conta Euphorbiacee_Euforbiacee indistinte 1 NUMERIC 0 0 20 048180 [SIM] Conta Mirtacee_Mirtacee indistinte 1 NUMERIC 0 0 20 048181 [SIM] Conta Platanacee_Platanacee indistinte 1 NUMERIC 0 0 20 048182 [SIM] Conta Aceraceae_Aceracee indistinte 1 NUMERIC 0 0 20 048183 [SIM] Conta Pinacee_Pinacee indistinte 1 NUMERIC 0 0 20 048184 [SIM] Conta Ciperacee_Ciperacee indistinte 1 NUMERIC 0 0 20 048185 [SIM] Conta Juglandacee_Juglandacee indistinte 1 NUMERIC 0 0 20 048186 [SIM] Conta Ippocastanacee_Ippocastanacee indistinte 1 NUMERIC 0 0 20 048187 [SIM] Conta Oleacee_Ligustro NUMERIC 0 0 20 dballe-7.7/tables/mkbdoc0000755000175000017500000000610512652630043012175 00000000000000#!/usr/bin/perl -w use strict; use warnings; my $op = $ARGV[0]; # Skip the declaration section my @vals; while () { push @vals, [unpack('xA6xA64xA24xA3xA12xA3xA24xA3xA10', $_)]; } # Now @vals contains an array of: # # [ # 0: B code # 1: Description # 2: BUFR units # 3: BUFR scale # 4: BUFR bit reference # 5: BUFR bit lenhth # 6: CREX units # 7: CREX scale # 8: CREX length # ] # # Only CREX data is used in the local B table sub mkformat($$$) { my ($unit, $len, $dec) = @_; $len = int($len); if ($unit =~ /^CHARACTER|^CODE TABLE/) { return "$len chars"; } elsif ($dec == 0) { return "$len digits"; } elsif ($dec > 0) { return '#' x ($len - $dec) . '.' . '#' x $dec; } elsif ($dec < 0) { return '#' x $len . '0' x (-$dec); } } #my $nc = '@{\hspace{0.5mm}}l@{\hspace{0.5mm}}'; #my $dsc = '@{\hspace{0.5mm}}p{2.0cm}@{\hspace{0.5mm}}'; #my $onc = '@{\hspace{0.5mm}}p{1.4cm}@{\hspace{0.5mm}}'; #my $cmc = '@{\hspace{0.5mm}}p{3.5cm}@{\hspace{0.5mm}}'; #print qq#{\\begin{scriptsize} #\\begin{longtable}{|$nc|$nc|$nc|$dsc|$onc|$onc|$onc|$cmc|} #\\hline #{\\em Name} & {\\em Unit} & {\\em Format} & {\\em Description} & {\\em On insert input} & {\\em On query input} & {\\em On output} & {\\em Comment} \\\\ #\\hline #\\endhead #\\hline #\\endfoot ##; if ($op eq 'tex') { my $nc = '@{\hspace{0.5mm}}l@{\hspace{0.5mm}}'; my $dsc = '@{\hspace{0.5mm}}p{8.0cm}@{\hspace{0.5mm}}'; print qq({\\begin{scriptsize} \\begin{longtable}{|$nc|$dsc|$nc|$nc|} \\hline {\\em Code} & {\\em Description} & {\\em Units} & {\\em Format} \\\\ \\hline \\endhead \\hline \\endfoot ); for my $d (@vals) { my ($code, $desc, $unit, $dec, $len) = @{$d}[0, 1, 6, 7, 8]; my $format = mkformat($unit, $len, $dec); $format =~ s/(\#+\.\#+)/{\\tiny $1}/; $unit =~ s/CHARACTER/Character/; $unit =~ s/(NUMERIC|NUMBER)/Numeric/; $desc =~ s/%/\\%/; $unit =~ s/%/\\%/; my $out = join(' & ', ($code, $desc, $unit, $format))." \\\\\n"; $out =~ s/(_|#)/\\$1/g; print $out; } print q(\hline \end{longtable} \end{scriptsize} ); } elsif ($op eq 'dox') { our ($code, $desc, $unit, $format); print q{/**@defgroup local_b_table Local B table @ingroup tables This table lists all the entries of the local B table. You can use them to provide context information for a measured value. Every entry is listed together with its measure unit, length in characters or digits and description. \verbatim }; format DoxTop = Code Description Unit Format . format Dox = @<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<< $code, $desc, $unit, $format . $^L = "\n\n"; $^ = "DoxTop"; $~ = "Dox"; for my $d (@vals) { my ($dec, $len); ($code, $desc, $unit, $dec, $len) = @{$d}[0, 1, 6, 7, 8]; $format = mkformat($unit, $len, $dec); $unit =~ s/CHARACTER/Character/; $unit =~ s/(NUMERIC|NUMBER)/Numeric/; write STDOUT; } print q{\endverbatim */ }; } else { die "unknown output format $op"; } exit 0; dballe-7.7/tables/B000000002001200.txt0000644000175000017500000004540012652630043013260 00000000000000 001001 WMO BLOCK NUMBER NUMERIC 0 0 7 001002 WMO STATION NUMBER NUMERIC 0 0 10 001007 SATELLITE IDENTIFIER CODE TABLE 1007 0 0 10 001008 AIRCRAFT REGISTRATION NUMBER OR OTHER IDENTIFICATION CCITTIA5 0 0 64 001011 SHIP OR MOBILE LAND STATION IDENTIFIER CCITTIA5 0 0 72 001012 DIRECTION OF MOTION OF MOVING OBSERVING PLATFORM** DEGREE TRUE 0 0 9 001013 SPEED OF MOTION OF MOVING OBSERVING PLATFORM* M/S 0 0 10 001019 LONG STATION OR SITE NAME CCITTIA5 0 0 256 001063 ICAO LOCATION INDICATOR CCITTIA5 0 0 64 001192 [SIM] MeteoDB station ID NUMERIC 0 0 24 001193 [SIM] Report code NUMERIC 0 0 16 001194 [SIM] Report mnemonic CCITTIA5 0 0 128 001212 AIR QUALITY OBSERVING STATION LOCAL CODE CCITTIA5 0 0 56 001213 AIRBASE AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 56 001214 GEMS AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 48 001215 AIR QUALITY OBSERVING STATION DOMINANT EMISSION SOURCE CODE TABLE 001215 0 0 3 001216 AIR QUALITY OBSERVING STATION AREA TYPE CODE TABLE 001216 0 0 3 001217 AIR QUALITY OBSERVING STATION TERRAIN TYPE CODE TABLE 001217 0 0 4 002001 TYPE OF STATION CODE TABLE 2001 0 0 2 002002 TYPE OF INSTRUMENTATION FOR WIND MEASUREMENT FLAG TABLE 2002 0 0 4 002005 PRECISION OF TEMPERATURE OBSERVATION K 2 0 7 002011 RADIOSONDE TYPE CODE TABLE 2011 0 0 8 002012 RADIOSONDE COMPUTATIONAL METHOD CODE TABLE 2012 0 0 4 002048 SATELLITE SENSOR INDICATOR CODE TABLE 2048 0 0 4 002061 AIRCRAFT NAVIGATIONAL SYSTEM CODE TABLE 2061 0 0 3 002062 TYPE OF AIRCRAFT DATA RELAY SYSTEM CODE TABLE 2062 0 0 4 002063 AIRCRAFT ROLL ANGLE DEGREE 2 -18000 16 002070 ORIGINAL SPECIFICATION OF LATITUDE/LONGITUDE CODE TABLE 2070 0 0 4 004001 YEAR YEAR 0 0 12 004002 MONTH MONTH 0 0 4 004003 DAY DAY 0 0 6 004004 HOUR HOUR 0 0 5 004005 MINUTE MINUTE 0 0 6 004006 SECOND SECOND 0 0 6 004192 [SIM] Time range type NUMERIC 0 0 10 004193 [SIM] Time range P1 NUMERIC 0 -536870912 31 004194 [SIM] Time range P2 NUMERIC 0 -536870912 31 005001 LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 005021 BEARING OR AZIMUTH DEGREE TRUE 2 0 16 005022 SOLAR AZIMUTH DEGREE TRUE 2 0 16 005040 ORBIT NUMBER NUMERIC 0 0 24 005041 SCAN LINE NUMBER NUMERIC 0 0 8 005043 FIELD OF VIEW NUMBER NUMERIC 0 0 8 006001 LONGITUDE (HIGH ACCURACY) DEGREE 5 -18000000 26 007001 HEIGHT OF STATION (SEE NOTE 1) M 0 -400 15 007002 HEIGHT OR ALTITUDE M -1 -40 16 007004 PRESSURE PA -1 0 14 007024 SATELLITE ZENITH ANGLE DEGREE 2 -9000 15 007025 SOLAR ZENITH ANGLE DEGREE 2 -9000 15 007031 HEIGHT OF BAROMETER ABOVE MEAN SEA LEVEL (SEE NOTE 4) M 1 - 4000 17 007192 [SIM] First level type NUMERIC 0 0 10 007193 [SIM] Level L1 NUMERIC 0 -536870912 31 007194 [SIM] Level L2 NUMERIC 0 -536870912 31 007195 [SIM] Second level type NUMERIC 0 0 31 008001 VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8001 0 0 7 008004 PHASE OF AIRCRAFT FLIGHT CODE TABLE 8004 0 0 3 008021 TIME SIGNIFICANCE CODE TABLE 8021 0 0 5 008044 (VAL) CAS REGISTRY NUMBER CCITTIA5 0 0 88 010003 GEOPOTENTIAL M**2/S**2 0 -4000 24 010004 PRESSURE PA -1 0 14 010007 HEIGHT M 0 -1000 17 010009 GEOPOTENTIAL HEIGHT GPM 0 -1000 17 010051 PRESSURE REDUCED TO MEAN SEA LEVEL PA -1 0 14 010052 ALTIMETER SETTING (QNH) PA -1 0 14 010061 3-HOUR PRESSURE CHANGE PA -1 -500 11 010063 CHARACTERISTIC OF PRESSURE TENDENCY CODE TABLE 10063 0 0 4 010197 ANEMOMETER HEIGHT M 0 0 9 011001 WIND DIRECTION DEGREE TRUE 0 0 9 011002 WIND SPEED M/S 1 0 12 011003 U-COMPONENT M/S 1 -4096 13 011004 V-COMPONENT M/S 1 -4096 13 011005 W-COMPONENT PA/S 1 -512 10 011006 W-COMPONENT M/S 2 -4096 13 011016 EXTREME COUNTERCLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 011017 EXTREME CLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 011041 MAXIMUM WIND GUST SPEED M/S 1 0 12 012001 TEMPERATURE/DRY-BULB TEMPERATURE K 1 0 12 012002 WET-BULB TEMPERATURE K 1 0 12 012003 DEW-POINT TEMPERATURE K 1 0 12 012030 SOIL TEMPERATURE K 1 0 12 012061 SKIN TEMPERATURE K 1 0 12 012063 BRIGHTNESS TEMPERATURE K 1 0 12 013001 SPECIFIC HUMIDITY KG/KG 5 0 14 013003 RELATIVE HUMIDITY % 0 0 7 013011 TOTAL PRECIPITATION / TOTAL WATER EQUIVALENT KG/M**2 1 -1 14 013013 TOTAL SNOW DEPTH M 3 -20 20 014016 NET RADIATION J/M**2 -4 -16384 15 014018 INSTANTANEOUS SHORT-WAVE RADIATION W/M**2 -3 -2048 12 014021 GLOBAL SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 014192 [SIM] Instantenous sensible heat flux W m-2 -3 -2048 12 014193 [SIM] Instantenous latent heat flux W m-2 -3 -2048 12 015192 [SIM] NO Concentration KG/M**3 10 0 14 015193 [SIM] NO2 Concentration KG/M**3 10 0 14 015194 [SIM] O3 Concentration KG/M**3 10 0 14 015195 [SIM] PM10 Concentration KG/M**3 10 0 14 015196 [SIM] CO Concentration KG/M**3 10 0 14 015197 [SIM] SO2 Concentration KG/M**3 10 0 14 015198 [SIM] PM2.5 Concentration KG/M**3 10 0 14 020001 HORIZONTAL VISIBILITY M -1 0 13 020003 PRESENT WEATHER (SEE NOTE 1) CODE TABLE 20003 0 0 9 020004 PAST WEATHER (1) (SEE NOTE 2) CODE TABLE 20004 0 0 5 020005 PAST WEATHER (2) (SEE NOTE 2) CODE TABLE 20005 0 0 5 020009 GENERAL WEATHER INDICATOR (TAF/METAR) CODE TABLE 20009 0 0 4 020010 CLOUD COVER (TOTAL) % 0 0 7 020011 CLOUD AMOUNT CODE TABLE 20011 0 0 4 020012 CLOUD TYPE CODE TABLE 20012 0 0 6 020013 HEIGHT OF BASE OF CLOUD M 0 -400 17 020019 SIGNIFICANT PRESENT OR FORECAST WEATHER CCITTIA5 0 0 72 020021 TYPE OF PRECIPITATION FLAG TABLE 20021 0 0 30 020062 STATE OF THE GROUND (WITH OR WITHOUT SNOW) CODE TABLE 20062 0 0 5 020193 [SIM] Cloud type (METAR) CCITTIA5 0 0 16 022001 DIRECTION OF WAVES DEGREE TRUE 0 0 9 022011 PERIOD OF WAVES S 0 0 6 022012 PERIOD OF WIND WAVES S 0 0 6 022021 HEIGHT OF WAVES M 1 0 10 022022 HEIGHT OF WIND WAVES M 1 0 10 022042 SEA/WATER TEMPERATURE K 1 0 12 022070 SIGNIFICANT WAVE HEIGHT M 2 0 13 022071 SPECTRAL PEAK WAVE PERIOD S 1 0 9 022074 AVERAGE WAVE PERIOD S 1 0 9 025076 LOG-10 OF (TEMP-RAD CENTRAL WAVENUMBER) FOR ATOVS LOGM-1 8 0 30 031000 SHORT DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 1 031001 DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 8 031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 16 031011 DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 8 031012 EXTENDED DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 16 031021 ASSOCIATED FIELD SIGNIFICANCE CODE TABLE 31021 0 0 6 031031 DATA PRESENT INDICATOR FLAG TABLE 31031 0 0 1 033002 QUALITY INFORMATION CODE TABLE 33002 0 0 2 033003 QUALITY INFORMATION CODE TABLE 33003 0 0 3 033005 QUALITY INFORMATION (AWS DATA) FLAG TABLE 33005 0 0 30 033006 INTERNAL MEASUREMENT STATUS INFORMATION (AWS) CODE TABLE 33006 0 0 3 033007 PER CENT CONFIDENCE % 0 0 7 033015 DATA QUALITY CHECK INDICATOR CODE TABLE 33015 0 0 6 033020 QUALITY CONTROL INDICATION OF FOLLOWING VALUE CODE TABLE 33020 0 0 3 033021 QUALITY OF FOLLOWING VALUE CODE TABLE 33021 0 0 2 033022 QUALITY OF BUOY SATELLITE TRANSMISSION CODE TABLE 33022 0 0 2 033023 QUALITY OF BUOY LOCATION CODE TABLE 33023 0 0 2 033024 STATION ELEVATION QUALITY MARK (FOR MOBILE STATIONS) CODE TABLE 33024 0 0 4 033025 ACARS INTERPOLATED VALUES CODE TABLE 33025 0 0 3 033026 MOISTURE QUALITY CODE TABLE 33026 0 0 6 033027 LOCATION QUALITY CLASS (RANGE OF RADIUS OF 66 % CONFIDENCE) CODE TABLE 33027 0 0 3 033030 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 33030 0 0 24 033031 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 33031 0 0 24 033032 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 33032 0 0 24 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS FLAG TABLE 33033 0 0 24 033035 MANUAL/AUTOMATIC QUALITY CONTROL CODE TABLE 33035 0 0 4 033036 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 033037 WIND CORRELATION ERROR FLAG TABLE 33037 0 0 20 033038 QUALITY FLAGS FOR GROUND-BASED GNSS DATA FLAG TABLE 33038 0 0 10 033040 CONFIDENCE INTERVAL % 0 0 7 033041 ATTRIBUTE OF FOLLOWING VALUE CODE TABLE 33041 0 0 2 033050 GLOBAL GTSPP QUALITY FLAG CODE TABLE 33050 0 0 4 033192 [SIM] Climatological and consistency check % 0 0 7 033193 [SIM] Time consistency % 0 0 7 033194 [SIM] Space consistency % 0 0 7 033195 [SIM] MeteoDB variable ID NUMERIC 0 0 24 033196 [SIM] Data has been invalidated CODE TABLE 33196 0 0 1 033197 [SIM] Manual replacement in substitution CODE TABLE 33197 0 0 2 033198 [SIM] Observation increment NUMERIC 4 -536870912 31 dballe-7.7/tables/B990203.txt0000644000175000017500000006130112652630043012420 00000000000000 001001 WMO BLOCK NUMBER NUMERIC 0 0 7 NUMERIC 0 2 001002 WMO STATION NUMBER NUMERIC 0 0 10 NUMERIC 0 3 001007 SATELLITE IDENTIFIER CODE TABLE 1007 0 0 10 CODE TABLE 1007 0 3 001008 AIRCRAFT REGISTRATION NUMBER OR OTHER IDENTIFICATION CCITTIA5 0 0 64 CHARACTER 0 8 001011 SHIP OR MOBILE LAND STATION IDENTIFIER CCITTIA5 0 0 72 CHARACTER 0 9 001012 DIRECTION OF MOTION OF MOVING OBSERVING PLATFORM** DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 001013 SPEED OF MOTION OF MOVING OBSERVING PLATFORM* M/S 0 0 10 M/S 0 3 001019 LONG STATION OR SITE NAME CCITTIA5 0 0 256 CHARACTER 0 32 001063 ICAO LOCATION INDICATOR CCITTIA5 0 0 64 CHARACTER 0 8 001192 [SIM] MeteoDB station ID NUMERIC 0 0 24 NUMERIC 0 8 001193 [SIM] Report code NUMERIC 0 0 16 NUMERIC 0 5 001194 [SIM] Report mnemonic CCITTIA5 0 0 128 CHARACTER 0 16 001212 AIR QUALITY OBSERVING STATION LOCAL CODE CCITTIA5 0 0 56 CHARACTER 0 7 001213 AIRBASE AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 56 CHARACTER 0 7 001214 GEMS AIR QUALITY OBSERVING STATION CODE CCITTIA5 0 0 48 CHARACTER 0 6 001215 AIR QUALITY OBSERVING STATION DOMINANT EMISSION SOURCE CODE TABLE 001215 0 0 3 CODE TABLE 001215 0 1 001216 AIR QUALITY OBSERVING STATION AREA TYPE CODE TABLE 001216 0 0 3 CODE TABLE 001216 0 1 001217 AIR QUALITY OBSERVING STATION TERRAIN TYPE CODE TABLE 001217 0 0 4 CODE TABLE 001217 0 2 002001 TYPE OF STATION CODE TABLE 2001 0 0 2 CODE TABLE 2001 0 1 002002 TYPE OF INSTRUMENTATION FOR WIND MEASUREMENT FLAG TABLE 2002 0 0 4 FLAG TABLE 2002 0 2 002005 PRECISION OF TEMPERATURE OBSERVATION K 2 0 7 K 2 3 002011 RADIOSONDE TYPE CODE TABLE 2011 0 0 8 CODE TABLE 2011 0 3 002012 RADIOSONDE COMPUTATIONAL METHOD CODE TABLE 2012 0 0 4 CODE TABLE 2012 0 2 002048 SATELLITE SENSOR INDICATOR CODE TABLE 2048 0 0 4 CODE TABLE 2048 0 2 002061 AIRCRAFT NAVIGATIONAL SYSTEM CODE TABLE 2061 0 0 3 CODE TABLE 2061 0 1 002062 TYPE OF AIRCRAFT DATA RELAY SYSTEM CODE TABLE 2062 0 0 4 CODE TABLE 2062 0 2 002063 AIRCRAFT ROLL ANGLE DEGREE 2 -18000 16 DEGREE 2 5 002070 ORIGINAL SPECIFICATION OF LATITUDE/LONGITUDE CODE TABLE 2070 0 0 4 CODE TABLE 2070 0 2 004001 YEAR YEAR 0 0 12 YEAR 0 4 004002 MONTH MONTH 0 0 4 MONTH 0 2 004003 DAY DAY 0 0 6 DAY 0 2 004004 HOUR HOUR 0 0 5 HOUR 0 2 004005 MINUTE MINUTE 0 0 6 MINUTE 0 2 004006 SECOND SECOND 0 0 6 SECOND 0 2 004192 [SIM] Time range type NUMERIC 0 0 10 NUMERIC 0 4 004193 [SIM] Time range P1 NUMERIC 0 -536870912 31 NUMERIC 0 10 004194 [SIM] Time range P2 NUMERIC 0 -536870912 31 NUMERIC 0 10 005001 LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 005021 BEARING OR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005022 SOLAR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005040 ORBIT NUMBER NUMERIC 0 0 24 NUMERIC 0 8 005041 SCAN LINE NUMBER NUMERIC 0 0 8 NUMERIC 0 3 005043 FIELD OF VIEW NUMBER NUMERIC 0 0 8 NUMERIC 0 3 006001 LONGITUDE (HIGH ACCURACY) DEGREE 5 -18000000 26 DEGREE 5 8 007001 HEIGHT OF STATION (SEE NOTE 1) M 0 -400 15 M 0 5 007002 HEIGHT OR ALTITUDE M -1 -40 16 M -1 5 007004 PRESSURE PA -1 0 14 PA -1 5 007024 SATELLITE ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007025 SOLAR ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007031 HEIGHT OF BAROMETER ABOVE MEAN SEA LEVEL (SEE NOTE 4) M 1 - 4000 17 M 1 5 007192 [SIM] First level type NUMERIC 0 0 10 NUMERIC 0 4 007193 [SIM] Level L1 NUMERIC 0 -536870912 31 NUMERIC 0 10 007194 [SIM] Level L2 NUMERIC 0 -536870912 31 NUMERIC 0 10 007195 [SIM] Second level type NUMERIC 0 0 31 NUMERIC 0 4 008001 VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8001 0 0 7 FLAG TABLE 8001 0 3 008004 PHASE OF AIRCRAFT FLIGHT CODE TABLE 8004 0 0 3 CODE TABLE 8004 0 1 008021 TIME SIGNIFICANCE CODE TABLE 8021 0 0 5 CODE TABLE 8021 0 2 008044 (VAL) CAS REGISTRY NUMBER CCITTIA5 0 0 88 CHARACTER 0 11 010003 GEOPOTENTIAL M**2/S**2 0 -4000 24 M**2/S**2 0 7 010004 PRESSURE PA -1 0 14 PA -1 5 010007 HEIGHT M 0 -1000 17 M 0 6 010009 GEOPOTENTIAL HEIGHT GPM 0 -1000 17 GPM 0 5 010051 PRESSURE REDUCED TO MEAN SEA LEVEL PA -1 0 14 PA -1 5 010052 ALTIMETER SETTING (QNH) PA -1 0 14 PA -1 5 010061 3-HOUR PRESSURE CHANGE PA -1 -500 11 PA -1 4 010063 CHARACTERISTIC OF PRESSURE TENDENCY CODE TABLE 10063 0 0 4 CODE TABLE 10063 0 2 010197 ANEMOMETER HEIGHT M 0 0 9 M 0 3 011001 WIND DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011002 WIND SPEED M/S 1 0 12 M/S 1 4 011003 U-COMPONENT M/S 1 -4096 13 M/S 1 4 011004 V-COMPONENT M/S 1 -4096 13 M/S 1 4 011005 W-COMPONENT PA/S 1 -512 10 PA/S 1 4 011006 W-COMPONENT M/S 2 -4096 13 M/S 2 4 011016 EXTREME COUNTERCLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011017 EXTREME CLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011041 MAXIMUM WIND GUST SPEED M/S 1 0 12 M/S 1 4 012001 TEMPERATURE/DRY-BULB TEMPERATURE K 1 0 12 K 1 4 012002 WET-BULB TEMPERATURE K 1 0 12 K 1 4 012003 DEW-POINT TEMPERATURE K 1 0 12 K 1 4 012030 SOIL TEMPERATURE K 1 0 12 K 1 4 012061 SKIN TEMPERATURE K 1 0 12 K 1 4 012063 BRIGHTNESS TEMPERATURE K 1 0 12 K 1 4 013001 SPECIFIC HUMIDITY KG/KG 5 0 14 KG/KG 5 5 013003 RELATIVE HUMIDITY % 0 0 7 % 0 3 013011 TOTAL PRECIPITATION / TOTAL WATER EQUIVALENT KG/M**2 1 -1 14 KG/M**2 1 5 013013 TOTAL SNOW DEPTH M 3 -20 20 M 3 6 014016 NET RADIATION J/M**2 -4 -16384 15 J/M**2 -4 5 014018 INSTANTANEOUS SHORT-WAVE RADIATION W/M**2 -3 -2048 12 W/M**2 -3 4 014021 GLOBAL SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 J/M**2 -4 5 014192 [SIM] Instantenous sensible heat flux W m-2 -3 -2048 12 W m-2 -3 4 014193 [SIM] Instantenous latent heat flux W m-2 -3 -2048 12 W m-2 -3 4 015192 [SIM] NO Concentration KG/M**3 10 0 14 KG/M**3 10 4 015193 [SIM] NO2 Concentration KG/M**3 10 0 14 KG/M**3 10 4 015194 [SIM] O3 Concentration KG/M**3 10 0 14 KG/M**3 10 4 015195 [SIM] PM10 Concentration KG/M**3 10 0 14 KG/M**3 10 4 015196 [SIM] CO Concentration KG/M**3 10 0 14 KG/M**3 10 4 015197 [SIM] SO2 Concentration KG/M**3 10 0 14 KG/M**3 10 4 015198 [SIM] PM2.5 Concentration KG/M**3 10 0 14 KG/M**3 10 4 020001 HORIZONTAL VISIBILITY M -1 0 13 M -1 4 020003 PRESENT WEATHER (SEE NOTE 1) CODE TABLE 20003 0 0 9 CODE TABLE 20003 0 3 020004 PAST WEATHER (1) (SEE NOTE 2) CODE TABLE 20004 0 0 5 CODE TABLE 20004 0 2 020005 PAST WEATHER (2) (SEE NOTE 2) CODE TABLE 20005 0 0 5 CODE TABLE 20005 0 2 020009 GENERAL WEATHER INDICATOR (TAF/METAR) CODE TABLE 20009 0 0 4 CODE TABLE 20009 0 2 020010 CLOUD COVER (TOTAL) % 0 0 7 % 0 3 020011 CLOUD AMOUNT CODE TABLE 20011 0 0 4 CODE TABLE 20011 0 2 020012 CLOUD TYPE CODE TABLE 20012 0 0 6 CODE TABLE 20012 0 2 020013 HEIGHT OF BASE OF CLOUD M 0 -400 17 M 0 5 020019 SIGNIFICANT PRESENT OR FORECAST WEATHER CCITTIA5 0 0 72 CHARACTER 0 9 020021 TYPE OF PRECIPITATION FLAG TABLE 20021 0 0 30 FLAG TABLE 20021 0 10 020062 STATE OF THE GROUND (WITH OR WITHOUT SNOW) CODE TABLE 20062 0 0 5 CODE TABLE 20062 0 2 020193 [SIM] Cloud type (METAR) CCITTIA5 0 0 16 CHARACTER 0 2 022001 DIRECTION OF WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022011 PERIOD OF WAVES S 0 0 6 S 0 2 022012 PERIOD OF WIND WAVES S 0 0 6 S 0 2 022021 HEIGHT OF WAVES M 1 0 10 M 1 4 022022 HEIGHT OF WIND WAVES M 1 0 10 M 1 4 022042 SEA/WATER TEMPERATURE K 1 0 12 K 1 4 022070 SIGNIFICANT WAVE HEIGHT M 2 0 13 M 2 4 022071 SPECTRAL PEAK WAVE PERIOD S 1 0 9 S 1 3 022074 AVERAGE WAVE PERIOD S 1 0 9 S 1 3 025076 LOG-10 OF (TEMP-RAD CENTRAL WAVENUMBER) FOR ATOVS LOGM-1 8 0 30 LOGM-1 8 10 031000 SHORT DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 1 NUMERIC 0 1 031001 DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031011 DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031012 EXTENDED DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031021 ASSOCIATED FIELD SIGNIFICANCE CODE TABLE 31021 0 0 6 CODE TABLE 31021 0 2 031031 DATA PRESENT INDICATOR FLAG TABLE 31031 0 0 1 FLAG TABLE 31031 0 1 033002 QUALITY INFORMATION CODE TABLE 33002 0 0 2 CODE TABLE 33002 0 1 033003 QUALITY INFORMATION CODE TABLE 33003 0 0 3 CODE TABLE 33003 0 1 033005 QUALITY INFORMATION (AWS DATA) FLAG TABLE 33005 0 0 30 FLAG TABLE 33005 0 10 033006 INTERNAL MEASUREMENT STATUS INFORMATION (AWS) CODE TABLE 33006 0 0 3 CODE TABLE 33006 0 1 033007 PER CENT CONFIDENCE % 0 0 7 % 0 3 033015 DATA QUALITY CHECK INDICATOR CODE TABLE 33015 0 0 6 CODE TABLE 33015 0 2 033020 QUALITY CONTROL INDICATION OF FOLLOWING VALUE CODE TABLE 33020 0 0 3 CODE TABLE 33020 0 1 033021 QUALITY OF FOLLOWING VALUE CODE TABLE 33021 0 0 2 CODE TABLE 33021 0 1 033022 QUALITY OF BUOY SATELLITE TRANSMISSION CODE TABLE 33022 0 0 2 CODE TABLE 33022 0 1 033023 QUALITY OF BUOY LOCATION CODE TABLE 33023 0 0 2 CODE TABLE 33023 0 1 033024 STATION ELEVATION QUALITY MARK (FOR MOBILE STATIONS) CODE TABLE 33024 0 0 4 CODE TABLE 33024 0 2 033025 ACARS INTERPOLATED VALUES CODE TABLE 33025 0 0 3 CODE TABLE 33025 0 1 033026 MOISTURE QUALITY CODE TABLE 33026 0 0 6 CODE TABLE 33026 0 2 033027 LOCATION QUALITY CLASS (RANGE OF RADIUS OF 66 % CONFIDENCE) CODE TABLE 33027 0 0 3 CODE TABLE 33027 0 1 033030 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 33030 0 0 24 FLAG TABLE 33030 0 8 033031 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 33031 0 0 24 FLAG TABLE 33031 0 8 033032 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 33032 0 0 24 FLAG TABLE 33032 0 8 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS FLAG TABLE 33033 0 0 24 FLAG TABLE 33033 0 8 033035 MANUAL/AUTOMATIC QUALITY CONTROL CODE TABLE 33035 0 0 4 CODE TABLE 33035 0 2 033036 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 % 0 3 033037 WIND CORRELATION ERROR FLAG TABLE 33037 0 0 20 FLAG TABLE 33037 0 7 033038 QUALITY FLAGS FOR GROUND-BASED GNSS DATA FLAG TABLE 33038 0 0 10 FLAG TABLE 33038 0 4 033040 CONFIDENCE INTERVAL % 0 0 7 PERCENT 0 3 033041 ATTRIBUTE OF FOLLOWING VALUE CODE TABLE 33041 0 0 2 CODE TABLE 33041 0 1 033050 GLOBAL GTSPP QUALITY FLAG CODE TABLE 33050 0 0 4 CODE TABLE 33050 0 2 033192 [SIM] Climatological and consistency check % 0 0 7 PERCENT 0 3 033193 [SIM] Time consistency % 0 0 7 PERCENT 0 3 033194 [SIM] Space consistency % 0 0 7 PERCENT 0 3 033195 [SIM] MeteoDB variable ID NUMERIC 0 0 24 NUMERIC 0 8 033196 [SIM] Data has been invalidated CODE TABLE 33196 0 0 1 CODE TABLE 33196 0 1 033197 [SIM] Manual replacement in substitution CODE TABLE 33197 0 0 2 CODE TABLE 33197 0 1 033198 [SIM] Observation increment NUMERIC 4 -536870912 31 NUMERIC 4 10 dballe-7.7/python/0000755000175000017500000000000012653425053011141 500000000000000dballe-7.7/python/test-volnd.py0000755000175000017500000004057512652630043013544 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import dballe from dballe.volnd import * import unittest, random, sys import datetime import warnings import numpy import numpy.ma as ma class TestTddiv(unittest.TestCase): # def tons(td): # return td.days * 86400000000 + td.seconds * 1000000 + td.microseconds def dtest(self, td1, td2): self.assertEqual(tddivmod1(td1, td2), tddivmod2(td1, td2)) q, r = tddivmod1(td1, td2) self.assertEqual(td2 * q + r, td1) if tddivmod3 is not None: self.assertEqual(tddivmod1(td1, td2), tddivmod3(td1, td2)) def testtddiv(self): #self.assertEqual(tddivmod(datetime.timedelta(10, 0, 0), datetime.timedelta(2, 0, 0)), (5, datetime.timedelta(0))) #self.assertEqual(tddivmod(datetime.timedelta(10, 0, 1), datetime.timedelta(2, 0, 0)), (5, datetime.timedelta(0, 0, 1))) #self.assertEqual(tddivmod(datetime.timedelta(10, 0, 1), datetime.timedelta(3, 0, 0)), (3, datetime.timedelta(1, 0, 1))) #self.assertEqual(tddivmod(datetime.timedelta(10, 6, 18), datetime.timedelta(5, 3, 9)), (2, datetime.timedelta(0))) #self.assertEqual(tddivmod(datetime.timedelta(3, 4, 5), datetime.timedelta(1, 3, 10)), (2, datetime.timedelta(0, 86397, 999985))) #self.assertEqual(tddivmod(datetime.timedelta(0, 4, 5), datetime.timedelta(0, 3, 10)), (1, datetime.timedelta(0, 0, 999995))) #self.assertEqual(tddivmod(datetime.timedelta(2, 40, 10), datetime.timedelta(0, 0, 5)), (34568000002, datetime.timedelta(0))) self.dtest(datetime.timedelta(10, 0, 0), datetime.timedelta(2, 0, 0)) self.dtest(datetime.timedelta(10, 0, 1), datetime.timedelta(2, 0, 0)) self.dtest(datetime.timedelta(10, 0, 1), datetime.timedelta(3, 0, 0)) self.dtest(datetime.timedelta(10, 6, 18), datetime.timedelta(5, 3, 9)) self.dtest(datetime.timedelta(3, 4, 5), datetime.timedelta(1, 3, 10)) self.dtest(datetime.timedelta(0, 4, 5), datetime.timedelta(0, 3, 10)) self.dtest(datetime.timedelta(2, 40, 10), datetime.timedelta(0, 0, 5)) # Re-enable when Debian bug #48872 has been fixed #self.dtest(datetime.timedelta(999999999, 86399, 999999), datetime.timedelta(0, 0, 2)) random.seed(1) for i in range(100): td1 = datetime.timedelta(random.randint(0, 999999999), random.randint(0, 86400), random.randint(0, 1000000)) td2 = datetime.timedelta(random.randint(0, 999999999), random.randint(0, 86400), random.randint(0, 1000000)) self.dtest(td1, td2) # Re-enable when Debian bug #48872 has been fixed #for i in xrange(100): # td1 = datetime.timedelta(random.randint(0, 999999999), random.randint(0, 86400), random.randint(0, 1000000)) # td2 = datetime.timedelta(0, random.randint(0, 86400), random.randint(0, 1000000)) # self.dtest(td1, td2) #for i in xrange(100): # td1 = datetime.timedelta(random.randint(0, 999999999), random.randint(0, 86400), random.randint(0, 1000000)) # td2 = datetime.timedelta(0, 0, random.randint(0, 1000000)) # self.dtest(td1, td2) #for i in xrange(100): # td1 = datetime.timedelta(0, random.randint(0, 86400), random.randint(0, 1000000)) # td2 = datetime.timedelta(0, 0, random.randint(0, 1000000)) # self.dtest(td1, td2) class TestRead(unittest.TestCase): def __init__(self, *args, **kw): super(TestRead, self).__init__(*args, **kw) if not hasattr(self, "assertCountEqual"): self.assertCountEqual = self.assertItemsEqual def setUp(self): from testlib import fill_volnd self.db = dballe.DB.connect_test() fill_volnd(self.db) def tearDown(self): #self.db.disconnect() pass def testIndexFind(self): # Ana in one dimension, network in the other query = dballe.Record(ana_id=1, var="B13011", rep_memo="synop") query["datetime"] = datetime.datetime(2007, 1, 1, 0, 0, 0) vars = read(self.db.query_data(query), (AnaIndex(), TimeRangeIndex())) self.assertEqual(vars["B13011"].dims[1].index((4, -21600, 0)), 1) def testFilter(self): # Ana in one dimension, network in the other query = dballe.Record(ana_id=1, var="B13011", rep_memo="synop") query["datetime"] = datetime.datetime(2007, 1, 1, 0, 0, 0) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) vars = read(self.db.query_data(query), \ (AnaIndex(), TimeRangeIndex()), \ filter=lambda rec: rec["trange"] == (4, -21600, 0)) self.assertEqual(vars["B13011"].dims[1].index((4, -21600, 0)), 0) def testUnsharedIndex(self): # Ana in one dimension, network in the other query = dballe.Record(ana_id=1, rep_memo="synop") vars = read(self.db.query_data(query), (AnaIndex(), TimeRangeIndex(), DateTimeIndex())) self.assertEqual(len(vars["B13011"].dims[2]), len(vars["B10004"].dims[2])) self.assertEqual(vars["B13011"].dims[2], vars["B10004"].dims[2]) vars = read(self.db.query_data(query), (AnaIndex(), TimeRangeIndex(), DateTimeIndex(shared=False))) self.assertNotEqual(len(vars["B13011"].dims[2]), len(vars["B10004"].dims[2])) def testConflicts(self): # Ana in one dimension, network in the other query = dballe.Record(ana_id=1, var="B13011") query["datetime"] = datetime.datetime(2007, 1, 1, 0, 0, 0) # Here conflicting values are overwritten vars = read(self.db.query_data(query), (AnaIndex(), ), checkConflicts=False) self.assertEqual(type(vars), dict) # Here insted they should be detected self.assertRaises(IndexError, read, self.db.query_data(query), (AnaIndex(),), checkConflicts=True) def testFixedIndex(self): # Ana in one dimension, network in the other query = dballe.Record(ana_id=1, rep_memo="synop", year=2007, month=1, day=1) vars = read(self.db.query_data(query), (AnaIndex(), TimeRangeIndex(frozen=True, start=((4, -21600, 0), (4, -43200, 0)) ) ), checkConflicts=False) self.assertEqual(len(vars["B13011"].dims[1]), 2) vars = read(self.db.query_data(query), (AnaIndex(), TimeRangeIndex()), checkConflicts=False) self.assertEqual(len(vars["B13011"].dims[1]), 3) vars = read(self.db.query_data(query), (AnaIndex(), LevelIndex(frozen=True, start=((1, None, None, None),))), checkConflicts=False) self.assertEqual(len(vars["B13011"].dims[1]), 1) vars = read(self.db.query_data(query), (AnaIndex(), LevelIndex()), checkConflicts=False) self.assertEqual(len(vars["B13011"].dims[1]), 2) def testAnaNetwork(self): # Ana in one dimension, network in the other query = dballe.Record() query["var"] = "B10004" query["datetime"] = datetime.datetime(2007, 1, 1, 0, 0, 0) vars = read(self.db.query_data(query), (AnaIndex(), NetworkIndex())) self.assertEqual(len(vars), 1) self.assertCountEqual(vars.keys(), ["B10004"]) data = vars["B10004"] self.assertEqual(data.name, "B10004") self.assertEqual(len(data.attrs), 0) self.assertEqual(len(data.dims), 2) self.assertEqual(len(data.dims[0]), 6) self.assertEqual(len(data.dims[1]), 2) self.assertEqual(data.vals.size, 12) self.assertEqual(data.vals.shape, (6, 2)) self.assertEqual(sum(data.vals.mask.flat), 1) self.assertEqual(round(ma.average(data.vals)), 83185) self.assertEqual(data.dims[0][0], (1, 10., 15., None)) self.assertEqual(data.dims[0][1], (2, 10., 25., None)) self.assertEqual(data.dims[0][2], (3, 20., 15., None)) self.assertEqual(data.dims[0][3], (4, 20., 25., None)) self.assertEqual(data.dims[0][4], (5, 30., 15., None)) self.assertEqual(data.dims[0][5], (6, 30., 25., None)) self.assertEqual(set(data.dims[1]), set(("temp", "synop"))) def testAnaTrangeNetwork(self): # 3 dimensions: ana, timerange, network # 2 variables query = dballe.Record(datetime=datetime.datetime(2007, 1, 1, 0, 0, 0)) vars = read(self.db.query_data(query), (AnaIndex(), TimeRangeIndex(shared=False), NetworkIndex())) self.assertEqual(len(vars), 2) self.assertEqual(sorted(vars.keys()), ["B10004", "B13011"]) data = vars["B10004"] self.assertEqual(data.name, "B10004") self.assertEqual(len(data.attrs), 0) self.assertEqual(len(data.dims), 3) self.assertEqual(len(data.dims[0]), 6) self.assertEqual(len(data.dims[1]), 1) self.assertEqual(len(data.dims[2]), 2) self.assertEqual(data.vals.size, 12) self.assertEqual(data.vals.shape, (6, 1, 2)) self.assertEqual(sum(data.vals.mask.flat), 1) self.assertEqual(round(ma.average(data.vals)), 83185) self.assertEqual(data.dims[0][0], (1, 10., 15., None)) self.assertEqual(data.dims[0][1], (2, 10., 25., None)) self.assertEqual(data.dims[0][2], (3, 20., 15., None)) self.assertEqual(data.dims[0][3], (4, 20., 25., None)) self.assertEqual(data.dims[0][4], (5, 30., 15., None)) self.assertEqual(data.dims[0][5], (6, 30., 25., None)) self.assertEqual(data.dims[1][0], (0, None, None)) self.assertEqual(set(data.dims[2]), set(("temp", "synop"))) data = vars["B13011"] self.assertEqual(data.name, "B13011") self.assertEqual(len(data.attrs), 0) self.assertEqual(len(data.dims), 3) self.assertEqual(len(data.dims[0]), 6) self.assertEqual(len(data.dims[1]), 2) self.assertEqual(len(data.dims[2]), 2) self.assertEqual(data.vals.size, 24) self.assertEqual(data.vals.shape, (6, 2, 2)) self.assertEqual(sum(data.vals.mask.flat), 0) self.assertAlmostEqual(ma.average(data.vals), 5.325, 6) self.assertEqual(data.dims[0][0], (1, 10., 15., None)) self.assertEqual(data.dims[0][1], (2, 10., 25., None)) self.assertEqual(data.dims[0][2], (3, 20., 15., None)) self.assertEqual(data.dims[0][3], (4, 20., 25., None)) self.assertEqual(data.dims[0][4], (5, 30., 15., None)) self.assertEqual(data.dims[0][5], (6, 30., 25., None)) self.assertEqual(data.dims[1][0], (4, -43200, 0)) self.assertEqual(data.dims[1][1], (4, -21600, 0)) self.assertEqual(set(data.dims[2]), set(("temp", "synop"))) self.assertEqual(vars["B10004"].dims[0], vars["B13011"].dims[0]) self.assertNotEqual(vars["B10004"].dims[1], vars["B13011"].dims[1]) self.assertEqual(vars["B10004"].dims[2], vars["B13011"].dims[2]) def testAttrs(self): # Same export as testAnaNetwork, but check that the # attributes are synchronised query = dballe.Record() query["var"] = "B10004" query["datetime"] = datetime.datetime(2007, 1, 1, 0, 0, 0) vars = read(self.db.query_data(query), (AnaIndex(), NetworkIndex()), attributes=True) self.assertEqual(len(vars), 1) self.assertCountEqual(vars.keys(), ["B10004"]) data = vars["B10004"] self.assertEqual(len(data.attrs), 2) self.assertCountEqual(sorted(data.attrs.keys()), ['B33007', 'B33040']) for net, a in ('synop', 'B33007'), ('temp', 'B33040'): self.assertEqual(data.dims, data.attrs[a].dims) self.assertEqual(data.vals.size, data.attrs[a].vals.size) self.assertEqual(data.vals.shape, data.attrs[a].vals.shape) # Find what is the network dimension where we have the attributes netidx = -1 for idx, n in enumerate(data.dims[1]): if n == net: netidx = idx break self.assertNotEqual(netidx, -1) # No attrs in the other network self.assertEqual([x for x in data.attrs[a].vals.mask[:,1-netidx].flat], [True]*len(data.attrs[a].vals.mask[:,1-netidx].flat)) # Same attrs as values in this network self.assertEqual([x for x in data.vals.mask[:,netidx].flat], [x for x in data.attrs[a].vals.mask[:,netidx].flat]) self.assertEqual(round(ma.average(data.attrs['B33007'].vals)), 32) self.assertEqual(round(ma.average(data.attrs['B33040'].vals)), 54) def testSomeAttrs(self): # Same export as testAnaNetwork, but check that the # attributes are synchronised query = dballe.Record() query["var"] = "B10004" query["datetime"] = datetime.datetime(2007, 1, 1, 0, 0, 0) vars = read(self.db.query_data(query), (AnaIndex(), NetworkIndex()), attributes=('B33040',)) self.assertEqual(len(vars), 1) self.assertCountEqual(vars.keys(), ["B10004"]) data = vars["B10004"] self.assertEqual(len(data.attrs), 1) self.assertCountEqual(data.attrs.keys(), ['B33040']) a = data.attrs['B33040'] self.assertEqual(data.dims, a.dims) self.assertEqual(data.vals.size, a.vals.size) self.assertEqual(data.vals.shape, a.vals.shape) # Find the temp index netidx = -1 for idx, n in enumerate(data.dims[1]): if n == "temp": netidx = idx break self.assertNotEqual(netidx, -1) # Only compare the values on the temp index self.assertEqual([x for x in a.vals.mask[:,1-netidx].flat], [True]*len(a.vals.mask[:,1-netidx].flat)) self.assertEqual([x for x in data.vals.mask[:,netidx].flat], [x for x in a.vals.mask[:,netidx].flat]) self.assertEqual(round(ma.average(a.vals)), 54) def testEmptyExport(self): query = dballe.Record() query["ana_id"] = 5000 vars = read(self.db.query_data(query), (AnaIndex(), NetworkIndex()), attributes=True) self.assertEqual(len(vars), 0) def testGhostIndexes(self): # If an index rejects a variable after another index # has successfuly added an item, we used to end up with # a 'ghost' index entry with no items in it indexes = (TimeRangeIndex(), \ LevelIndex(frozen=True, start=((3, 2, None, None),) )) query = dballe.Record() query['ana_id'] = 1 query['var'] = 'B13011' vars = read(self.db.query_data(query), indexes, \ checkConflicts=False) self.assertCountEqual(vars.keys(), ["B13011"]) self.assertEqual(len(vars["B13011"].dims[1]), 1) self.assertEqual(vars["B13011"].dims[0][0], (4, -21600, 0)) def testBuggyExport1(self): indexes = (AnaIndex(), LevelIndex(frozen=True, start=((1, None, None), (3, 2, None))), TimeRangeIndex(), DateTimeIndex()) query = dballe.Record() query['rep_memo'] = 'synop' vars = read(self.db.query_data(query), indexes, checkConflicts=True, attributes=True) def testExportAna(self): indexes = (AnaIndex(),) query = dballe.Record() query["rep_memo"] = "synop" vars = read(self.db.query_station_data(query), indexes, checkConflicts=True) self.assertEqual(sorted(vars.keys()), ["B01001", "B01002", "B01019"]) def testExportSyncAna(self): # Export some data indexes = (AnaIndex(), DateTimeIndex()) query = dballe.Record() query["rep_memo"] = 'synop' query["level"] = (1,) query["trange"] = (4, -21600, 0) vars = read(self.db.query_data(query), indexes, checkConflicts=True) self.assertEqual(sorted(vars.keys()), ["B13011"]) # Freeze all the indexes for i in range(len(indexes)): indexes[i].freeze() # Export the pseudoana data in sync with the data query.clear() query["rep_memo"] = "synop" anas = read(self.db.query_station_data(query), (indexes[0],), checkConflicts=True) self.assertEqual(sorted(anas.keys()), ["B01001", "B01002", "B01019"]) self.assertEqual(anas["B01001"].dims[0], vars["B13011"].dims[0]) if __name__ == "__main__": from testlib import main main("test_volnd") dballe-7.7/python/doc-dballe0000755000175000017500000001652212652630043012777 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import os os.environ["DBALLE_BUILDING_DOCS"]="true" try: import rpy_options rpy_options.set_options(VERBOSE=False) except ImportError: pass import sys import inspect import dballe import dballe.volnd import dballe.rconvert def print_indented(spaces, *args): "Print a string, indented by the given number of spaces" for s in args: for line in s.split("\n"): for i in range(1,spaces): sys.stdout.write(" ") sys.stdout.write(line) sys.stdout.write("\n") c_argspecs = { "dballe.varinfo": "(varcode)", "dballe.var": "(varcode[, default])", "dballe.describe_level": "(ltype1=None, l1=None, ltype2=None, l2=None)", "dballe.describe_trange": "(pind=None, p1=None, p2=None)", "Var.enqi": "()", "Var.enqc": "()", "Var.enqd": "()", "Var.enq": "()", "Var.get": "(default=None)", "Var.format": "(default='')", "Record.clear": "()", "Record.clear_vars": "()", "Record.get": "(key, default=None)", "Record.copy": "()", "Record.key": "(key)", "Record.var": "(key)", "Record.keys": "()", "Record.items": "()", "Record.varitems": "()", "Record.vars": "()", "Record.update": "(\*\*kwargs)", "Record.date_extremes": "()", "Record.set_station_context": "()", "Record.set_from_string": "(str)", "DB.connect": "(dsn, user='', password='')", "DB.connect_from_file": "(filename)", "DB.connect_from_url": "(url)", "DB.connect_test": "()", "DB.is_url": "(string)", "DB.disappear": "()", "DB.reset": "([repinfo_filename])", "DB.insert": "(record, can_replace=False, can_add_stations=False)", "DB.remove": "(query)", "DB.vacuum": "()", "DB.query_reports": "(query)", "DB.query_stations": "(query)", "DB.query_levels": "(query)", "DB.query_tranges": "(query)", "DB.query_variable_types": "(query)", "DB.query_summary": "(query)", "DB.query_data": "(query)", "DB.query_datetime_extremes": "(query)", "DB.attr_insert": "(varcode, attrs, reference_id=None, replace=True)", "DB.attr_remove": "(varcode, reference_id, attrs=None)", "DB.query_attrs": "(varcode, reference_id, attrs=None)", "DB.load": "(file)", "DB.export_to_file": "(query, format, filename, generic=False)", "Cursor.next": "()", "Cursor.query_attrs": "(attrs=None)", } def document_class(cls): name = cls.__name__ print() print("dballe.{}".format(name)) print("-" * (len(name) + 7)) print() print(inspect.getdoc(cls)) print() print("Members") print("```````") document_members(cls) def document(obj): if obj.__doc__ == None: return if inspect.ismodule(obj): print_indented(0, inspect.getdoc(obj)) print elif inspect.isroutine(obj) and inspect.isfunction(obj): # A Python function print_indented(2, '``'+obj.__name__ + inspect.formatargspec(*inspect.getargspec(obj))+"``") print_indented(4, inspect.getdoc(obj)) else: print_indented(2, obj.__name__) print_indented(4, inspect.getdoc(obj)) def document_members(cls): # List and classify members member_vars = [] member_funcs = [] for name, m in inspect.getmembers(cls): if name[0] == '_': continue fullname = cls.__name__ + "." + name if inspect.isroutine(m) and (inspect.isfunction(m) or fullname in c_argspecs): member_funcs.append((fullname, name, m)) elif inspect.isclass(m) or inspect.ismodule(m): pass elif m.__class__.__name__ == "_Feature": pass else: member_vars.append((fullname, name, m)) member_vars.sort() member_funcs.sort() # Document vars and get/setters for fullname, name, m in member_vars: print(".. _{}.{}:".format(cls.__name__, name)) for fullname, name, m in member_funcs: print(".. _{}.{}():".format(cls.__name__, name)) print() for fullname, name, m in member_vars: print_indented(2, name) print_indented(4, inspect.getdoc(m)) # Document functions for fullname, name, m in member_funcs: argspec = c_argspecs.get(fullname, None) if argspec is None: if inspect.isfunction(m): argspec = inspect.formatargspec(*inspect.getargspec(m)) else: argspec = "" print_indented(2, name + argspec) print_indented(4, inspect.getdoc(m)) print("""=================================== README for DB-All.e Python bindings =================================== The DB-All.e Python bindings provide 2 levels of access to a DB-All.e database: a complete API similar to the Fortran and C++ API, and a high-level API called volnd that allows to automatically export matrices of data out of the database. .. contents:: The DB-All.e API ================ The 'dballe' module has a few global methods: """) document_members(dballe) print(""" and several classes, documented in their own sections. """) document_class(dballe.Var) document_class(dballe.Varinfo) document_class(dballe.Vartable) document_class(dballe.Record) print(""" dballe.DB --------- a DB is used to access the database. Its members are: """) document_members(dballe.DB) print(""" Examples: :: # Connect to a database and run a query db = dballe.DB.connect_from_file("db.sqlite") query = dballe.Record(latmin=44.0, latmax=45.0, lonmin=11.0, lonmax=12.0) # The result is a dballe.Cursor, which can be iterated to get results as # dballe.Record objects. # The results always point to the same Record to avoid creating a new one # for every iteration: if you need to store them, use Record.copy() for rec in db.query_data(query): print rec["lat"], rec["lon"], rec["var"], rec.var().format("undefined") # Insert 2 new variables in the database rec = dballe.Record( lat=44.5, lon=11.4, level=(1,), trange=(254,), date=datetime.datetime(2013, 4, 25, 12, 0, 0), B11101=22.4, B12103=17.2, ) db.insert(rec) dballe.Cursor ------------- a Cursor is the result of database queries. It is generally not used explicitly and just iterated, but it does have a few members: """) document_members(dballe.Cursor) print(""" The volnd API ============= """) document(dballe.volnd) print(""" This is the list of dimensions supported by dballe.volnd: """) document (dballe.volnd.AnaIndex) document (dballe.volnd.NetworkIndex) document (dballe.volnd.LevelIndex) document (dballe.volnd.TimeRangeIndex) document (dballe.volnd.DateTimeIndex) document (dballe.volnd.IntervalIndex) print(""" The data object used by ``AnaIndex`` is: """) document (dballe.volnd.AnaIndexEntry) print(""" The extraction is done using the dballe.volnd.read function: """) document (dballe.volnd.read) print(""" The result of dballe.volnd.read is a dict mapping output variable names to a dballe.volnd.Data object with the results. All the Data objects share their indexes unless the *xxx*-Index definitions have been created with ``shared=False``. This is the dballe.volnd.Data class documentation: """) document (dballe.volnd.Data) print(""" The methods of dballe.volnd.Data are: """) document_members(dballe.volnd.Data) dballe-7.7/python/common.h0000644000175000017500000001052712652630043012523 00000000000000#ifndef DBALLE_PYTHON_COMMON_H #define DBALLE_PYTHON_COMMON_H #include #include #include #include #include namespace dballe { namespace python { extern wrpy_c_api* wrpy; /** * unique_ptr-like object that contains PyObject pointers, and that calls * Py_DECREF on destruction. */ template class py_unique_ptr { protected: Obj* ptr; public: py_unique_ptr(Obj* o) : ptr(o) {} py_unique_ptr(const py_unique_ptr&) = delete; py_unique_ptr(py_unique_ptr&& o) : ptr(o.ptr) { o.ptr = nullptr; } ~py_unique_ptr() { Py_XDECREF(ptr); } py_unique_ptr& operator=(const py_unique_ptr&) = delete; py_unique_ptr& operator=(py_unique_ptr&& o) { if (this == &o) return *this; Py_XDECREF(ptr); ptr = o.ptr; o.ptr = nullptr; return *this; } /// Release the reference without calling Py_DECREF Obj* release() { Obj* res = ptr; ptr = nullptr; return res; } /// Use it as a Obj operator Obj*() { return ptr; } /// Get the pointer (useful for passing to Py_BuildValue) Obj* get() { return ptr; } /// Check if ptr is not nullptr operator bool() const { return ptr; } }; typedef py_unique_ptr pyo_unique_ptr; /** * Return a python string representing a varcode */ PyObject* format_varcode(wreport::Varcode code); /// Given a wreport exception, set the Python error indicator appropriately. void set_wreport_exception(const wreport::error& e); /** * Given a wreport exception, set the Python error indicator appropriately. * * @retval * Always returns NULL, so one can do: * try { * // ...code... * } catch (wreport::error& e) { * return raise_wreport_exception(e); * } */ PyObject* raise_wreport_exception(const wreport::error& e); /// Given a generic exception, set the Python error indicator appropriately. void set_std_exception(const std::exception& e); /** * Given a generic exception, set the Python error indicator appropriately. * * @retval * Always returns NULL, so one can do: * try { * // ...code... * } catch (std::exception& e) { * return raise_std_exception(e); * } */ PyObject* raise_std_exception(const std::exception& e); #define DBALLE_CATCH_RETURN_PYO \ catch (wreport::error& e) { \ set_wreport_exception(e); return nullptr; \ } catch (std::exception& se) { \ set_std_exception(se); return nullptr; \ } #define DBALLE_CATCH_RETURN_INT \ catch (wreport::error& e) { \ set_wreport_exception(e); return -1; \ } catch (std::exception& se) { \ set_std_exception(se); return -1; \ } /// Convert a Datetime to a python datetime object PyObject* datetime_to_python(const Datetime& dt); /// Convert a python datetime object to a Datetime int datetime_from_python(PyObject* dt, Datetime& out); /// Convert a sequence of two python datetime objects to a DatetimeRange int datetimerange_from_python(PyObject* dt, DatetimeRange& out); /// Convert a Level to a python 4-tuple PyObject* level_to_python(const Level& lev); /// Convert a 4-tuple to a Level int level_from_python(PyObject* o, Level& out); /// Convert a Trange to a python 3-tuple PyObject* trange_to_python(const Trange& tr); /// Convert a 3-tuple to a Trange int trange_from_python(PyObject* o, Trange& out); /// Convert a python string, bytes or unicode to an utf8 string int string_from_python(PyObject* o, std::string& out); /// Call repr() on \a o, and return the result in \a out int object_repr(PyObject* o, std::string& out); /** * call o.fileno() and return its result. * * In case of AttributeError and IOError (parent of UnsupportedOperation, not * available from C), it clear the error indicator. * * Returns -1 if fileno() was not available or some other exception happened. * Use PyErr_Occurred to tell between the two. */ int file_get_fileno(PyObject* o); /** * call o.data() and return its result, both as a PyObject and as a buffer. * * The data returned in buf and len will be valid as long as the returned * object stays valid. */ PyObject* file_get_data(PyObject* o, char*&buf, Py_ssize_t& len); /** * Initialize the python bits to use used by the common functions. * * This can be called multiple times and will execute only once. */ int common_init(); } } #endif dballe-7.7/python/MANIFEST.in0000644000175000017500000000001412652630043012606 00000000000000include *.h dballe-7.7/python/Makefile.in0000644000175000017500000007573712652630335013151 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_RST2HTML_TRUE@am__append_1 = python-dballe.html subdir = python ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/m4_ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(pkgpython_PYTHON) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pyexecdir)" "$(DESTDIR)$(pkgpythondir)" \ "$(DESTDIR)$(docdir)" LTLIBRARIES = $(pyexec_LTLIBRARIES) _dballe_la_DEPENDENCIES = ../dballe/libdballe.la am__dballe_la_OBJECTS = _dballe_la-common.lo _dballe_la-record.lo \ _dballe_la-dballe.lo _dballe_la-db.lo _dballe_la-cursor.lo _dballe_la_OBJECTS = $(am__dballe_la_OBJECTS) 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 = _dballe_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(_dballe_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(_dballe_la_SOURCES) DIST_SOURCES = $(_dballe_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile) am__pep3147_tweak = \ sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|' py_compile = $(top_srcdir)/py-compile DATA = $(doc_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ $(top_srcdir)/py-compile DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FC = @FC@ FCFLAGS = @FCFLAGS@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDBALLEF_VERSION_INFO = @LIBDBALLEF_VERSION_INFO@ LIBDBALLE_VERSION_INFO = @LIBDBALLE_VERSION_INFO@ LIBOBJS = @LIBOBJS@ LIBPQ_CFLAGS = @LIBPQ_CFLAGS@ LIBPQ_LIBS = @LIBPQ_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ WREPORT_CFLAGS = @WREPORT_CFLAGS@ WREPORT_LIBS = @WREPORT_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_FC = @ac_ct_FC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_doxygen = @have_doxygen@ have_gperf = @have_gperf@ have_latex2html = @have_latex2html@ have_rst2html = @have_rst2html@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mysql_config = @mysql_config@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ tabledir = @tabledir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ TESTS_ENVIRONMENT = $(top_srcdir)/extra/runtest dballe_python_tests = test-core.py test-record.py test-db.py test-volnd.py test-rconvert.py test-csv.py # TESTS = $(dballe_python_tests) pkgpython_PYTHON = dballe/dbacsv.py dballe/rconvert.py dballe/__init__.py dballe/volnd.py pyexec_LTLIBRARIES = _dballe.la _dballe_la_SOURCES = \ common.cc \ record.cc \ dballe.cc \ db.cc \ cursor.cc _dballe_la_CPPFLAGS = $(PYTHON_CFLAGS) _dballe_la_LDFLAGS = -module -avoid-version -export-symbols-regex init_dballe _dballe_la_LIBADD = ../dballe/libdballe.la doc_DATA = python-dballe.rst $(am__append_1) EXTRA_DIST = \ doc-dballe \ common.h \ record.h \ db.h \ cursor.h \ testlib.py \ MANIFEST.in \ setup.py \ $(dballe_python_tests) AM_CPPFLAGS = -I/usr/include/python$(PYTHON_VERSION) -I$(top_srcdir) CLEANFILES = python-dballe.rst python-dballe.html all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign python/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *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);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-pyexecLTLIBRARIES: $(pyexec_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(pyexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pyexecdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pyexecdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pyexecdir)"; \ } uninstall-pyexecLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pyexecdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pyexecdir)/$$f"; \ done clean-pyexecLTLIBRARIES: -test -z "$(pyexec_LTLIBRARIES)" || rm -f $(pyexec_LTLIBRARIES) @list='$(pyexec_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } _dballe.la: $(_dballe_la_OBJECTS) $(_dballe_la_DEPENDENCIES) $(EXTRA__dballe_la_DEPENDENCIES) $(AM_V_CXXLD)$(_dballe_la_LINK) -rpath $(pyexecdir) $(_dballe_la_OBJECTS) $(_dballe_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_dballe_la-common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_dballe_la-cursor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_dballe_la-db.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_dballe_la-dballe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_dballe_la-record.Plo@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< _dballe_la-common.lo: common.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT _dballe_la-common.lo -MD -MP -MF $(DEPDIR)/_dballe_la-common.Tpo -c -o _dballe_la-common.lo `test -f 'common.cc' || echo '$(srcdir)/'`common.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_dballe_la-common.Tpo $(DEPDIR)/_dballe_la-common.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common.cc' object='_dballe_la-common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o _dballe_la-common.lo `test -f 'common.cc' || echo '$(srcdir)/'`common.cc _dballe_la-record.lo: record.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT _dballe_la-record.lo -MD -MP -MF $(DEPDIR)/_dballe_la-record.Tpo -c -o _dballe_la-record.lo `test -f 'record.cc' || echo '$(srcdir)/'`record.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_dballe_la-record.Tpo $(DEPDIR)/_dballe_la-record.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='record.cc' object='_dballe_la-record.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o _dballe_la-record.lo `test -f 'record.cc' || echo '$(srcdir)/'`record.cc _dballe_la-dballe.lo: dballe.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT _dballe_la-dballe.lo -MD -MP -MF $(DEPDIR)/_dballe_la-dballe.Tpo -c -o _dballe_la-dballe.lo `test -f 'dballe.cc' || echo '$(srcdir)/'`dballe.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_dballe_la-dballe.Tpo $(DEPDIR)/_dballe_la-dballe.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dballe.cc' object='_dballe_la-dballe.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o _dballe_la-dballe.lo `test -f 'dballe.cc' || echo '$(srcdir)/'`dballe.cc _dballe_la-db.lo: db.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT _dballe_la-db.lo -MD -MP -MF $(DEPDIR)/_dballe_la-db.Tpo -c -o _dballe_la-db.lo `test -f 'db.cc' || echo '$(srcdir)/'`db.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_dballe_la-db.Tpo $(DEPDIR)/_dballe_la-db.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='db.cc' object='_dballe_la-db.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o _dballe_la-db.lo `test -f 'db.cc' || echo '$(srcdir)/'`db.cc _dballe_la-cursor.lo: cursor.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT _dballe_la-cursor.lo -MD -MP -MF $(DEPDIR)/_dballe_la-cursor.Tpo -c -o _dballe_la-cursor.lo `test -f 'cursor.cc' || echo '$(srcdir)/'`cursor.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_dballe_la-cursor.Tpo $(DEPDIR)/_dballe_la-cursor.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='cursor.cc' object='_dballe_la-cursor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_dballe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o _dballe_la-cursor.lo `test -f 'cursor.cc' || echo '$(srcdir)/'`cursor.cc mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgpythonPYTHON: $(pkgpython_PYTHON) @$(NORMAL_INSTALL) @list='$(pkgpython_PYTHON)'; dlist=; list2=; test -n "$(pkgpythondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgpythondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgpythondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgpythondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgpythondir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(pkgpythondir)" $$dlist; \ else :; fi uninstall-pkgpythonPYTHON: @$(NORMAL_UNINSTALL) @list='$(pkgpython_PYTHON)'; test -n "$(pkgpythondir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ 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 \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(LTLIBRARIES) $(DATA) installdirs: for dir in "$(DESTDIR)$(pyexecdir)" "$(DESTDIR)$(pkgpythondir)" "$(DESTDIR)$(docdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local \ clean-pyexecLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-docDATA install-pkgpythonPYTHON install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pyexecLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-docDATA uninstall-pkgpythonPYTHON \ uninstall-pyexecLTLIBRARIES .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 \ 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 \ install install-am install-data install-data-am \ install-docDATA install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-pkgpythonPYTHON install-ps install-ps-am \ install-pyexecLTLIBRARIES install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-docDATA \ uninstall-pkgpythonPYTHON uninstall-pyexecLTLIBRARIES .PRECIOUS: Makefile export PYTHONPATH=. _dballe.so: _dballe.la ln -fs .libs/_dballe.so $@ python-dballe.rst: doc-dballe $(pkgpython_PYTHON) _dballe.so $(PYTHON) $(srcdir)/doc-dballe > $@ || (rm -f $@; false) python-dballe.html: python-dballe.rst rst2html $< > $@ || (rm -f $@; false) clean-local: rm -f *.pyc dballe/*.pyc _dballe.so rm -rf __pycache__ dballe/__pycache__ check-local: _dballe.so for test in $(dballe_python_tests); do \ PYTHON="$(PYTHON)" $(TESTS_ENVIRONMENT) $$test ; \ done # 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: dballe-7.7/python/setup.py0000644000175000017500000000215312652630043012570 00000000000000from setuptools import Extension, setup, command import subprocess def pkg_config_flags(options): return [ s for s in subprocess.check_output(['pkg-config'] + options + ['libdballe']).decode().strip().split(" ") if s ] dballe_module = Extension( '_dballe', sources=[ "common.cc", "cursor.cc", "dballe.cc", "db.cc", "record.cc", ], language="c++", extra_compile_args=pkg_config_flags(["--cflags"]) + ["-std=c++11"], extra_link_args=pkg_config_flags(["--libs"]), ) setup( name="dballe", version="7.6.0", author="Enrico Zini", author_email="enrico@enricozini.org", maintainer="Emanuele Di Giacomo", maintainer_email="edigiacomo@arpa.emr.it", description="Fast on-disk database for meteorological data", long_description="Fast on-disk database for meteorological data", url="http://github.com/arpa-simc/dballe", license="GPLv2+", py_modules=[], packages=['dballe'], data_files=[], zip_safe=False, include_package_data=True, exclude_package_data={}, ext_modules=[dballe_module], install_requires=['wreport'], ) dballe-7.7/python/record.cc0000644000175000017500000006607012652630043012653 00000000000000#include #include #include #include "record.h" #include "common.h" #include #include "config.h" #if PY_MAJOR_VERSION >= 3 #define PyInt_FromLong PyLong_FromLong #define PyInt_AsLong PyLong_AsLong #define PyInt_Check PyLong_Check #define Py_TPFLAGS_HAVE_ITER 0 #endif using namespace std; using namespace dballe; using namespace dballe::python; using namespace wreport; extern "C" { static const char* level_keys[4] = { "leveltype1", "l1", "leveltype2", "l2" }; static const char* trange_keys[3] = { "pindicator", "p1", "p2" }; static int any_key_set(const Record& rec, const char** keys, unsigned len) { for (unsigned i = 0; i < len; ++i) if (rec.isset(keys[i])) return 1; return 0; } /* * Record */ static int dpy_Record_setitem(dpy_Record* self, PyObject *key, PyObject *val); static int dpy_Record_contains(dpy_Record* self, PyObject *value); static PyObject* dpy_Record_getitem(dpy_Record* self, PyObject* key); static PyObject* dpy_Record_getitem(dpy_Record* self, PyObject* key) { string varname; if (string_from_python(key, varname)) return nullptr; try { // Just look at the first character to see if we need to check for python // API specific keys switch (varname[0]) { case 'd': if (varname == "datetime" || varname == "date") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return NULL; auto dt = core::Record::downcast(*self->rec).get_datetime(); if (!dt.is_missing()) return datetime_to_python(dt); PyErr_SetString(PyExc_KeyError, varname.c_str()); return NULL; } else if (varname == "datemin") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return NULL; auto dt = core::Record::downcast(*self->rec).get_datetimerange().min; if (!dt.is_missing()) return datetime_to_python(dt); PyErr_SetString(PyExc_KeyError, varname.c_str()); return NULL; } else if (varname == "datemax") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return NULL; auto dt = core::Record::downcast(*self->rec).get_datetimerange().max; if (!dt.is_missing()) return datetime_to_python(dt); PyErr_SetString(PyExc_KeyError, varname.c_str()); return NULL; } break; case 'l': if (varname == "level") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return NULL; auto lev = core::Record::downcast(*self->rec).get_level(); if (!lev.is_missing()) return level_to_python(lev); PyErr_SetString(PyExc_KeyError, varname.c_str()); return NULL; } break; case 't': if (varname == "trange" || varname == "timerange") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return NULL; auto tr = core::Record::downcast(*self->rec).get_trange(); if (!tr.is_missing()) return trange_to_python(tr); PyErr_SetString(PyExc_KeyError, varname.c_str()); return NULL; } break; } const Var* var = self->rec->get(varname.c_str()); if (var == NULL) { PyErr_SetString(PyExc_KeyError, varname.c_str()); return NULL; } if (!var->isset()) { PyErr_SetString(PyExc_KeyError, varname.c_str()); return NULL; } return wrpy->var_value_to_python(*var); } DBALLE_CATCH_RETURN_PYO } static int dpy_Record_setitem(dpy_Record* self, PyObject *key, PyObject *val) { string varname; if (string_from_python(key, varname)) return -1; try { // Check for shortcut keys if (varname == "datetime" || varname == "date") { if (varname == "date") if (int res = PyErr_WarnEx(PyExc_DeprecationWarning, "please use rec[\"datetime\"] instead of rec[\"date\"]", 1)) return res; if (val && PySequence_Check(val)) { DatetimeRange dtr; if (datetimerange_from_python(val, dtr)) return -1; self->rec->set(dtr); } else { Datetime dt; if (datetime_from_python(val, dt)) return -1; self->rec->set(dt); } self->station_context = false; return 0; } if (varname == "datemin") { if (int res = PyErr_WarnEx(PyExc_DeprecationWarning, "please use rec[\"datetime\"] = (min, max) instead of rec[\"datemin\"]", 1)) return res; DatetimeRange dtr = core::Record::downcast(*self->rec).get_datetimerange(); if (datetime_from_python(val, dtr.min)) return -1; self->rec->set(dtr); self->station_context = false; return 0; } if (varname == "datemax") { if (int res = PyErr_WarnEx(PyExc_DeprecationWarning, "please use rec[\"datetime\"] = (min, max) instead of rec[\"datemax\"]", 1)) return res; DatetimeRange dtr = core::Record::downcast(*self->rec).get_datetimerange(); if (datetime_from_python(val, dtr.max)) return -1; self->rec->set(dtr); self->station_context = false; return 0; } if (varname == "level") { Level lev; if (level_from_python(val, lev)) return -1; self->station_context = false; self->rec->set(lev); return 0; } if (varname == "trange" || varname == "timerange") { if (varname == "timerange") if (int res = PyErr_WarnEx(PyExc_DeprecationWarning, "please use rec[\"trange\"] instead of rec[\"timerange\"]", 1)) return res; Trange tr; if (trange_from_python(val, tr)) return -1; self->station_context = false; self->rec->set(tr); return 0; } if (!val) { // del rec[val] self->rec->unset(varname.c_str()); return 0; } if (PyFloat_Check(val)) { double v = PyFloat_AsDouble(val); if (v == -1.0 && PyErr_Occurred()) return -1; self->rec->set(varname.c_str(), v); } else if (PyInt_Check(val)) { long v = PyInt_AsLong(val); if (v == -1 && PyErr_Occurred()) return -1; self->rec->set(varname.c_str(), (int)v); } else if ( PyUnicode_Check(val) #if PY_MAJOR_VERSION >= 3 || PyBytes_Check(val) #else || PyString_Check(val) #endif ) { string value; if (string_from_python(val, value)) return -1; self->rec->set(varname.c_str(), value.c_str()); } else if (val == Py_None) { self->rec->unset(varname.c_str()); } else { PyErr_SetString(PyExc_TypeError, "Expected int, float, str, unicode, or None"); return -1; } return 0; } DBALLE_CATCH_RETURN_INT } static int dpy_Record_contains(dpy_Record* self, PyObject *value) { string varname; if (string_from_python(value, varname)) return -1; switch (varname[0]) { case 'd': // We don't bother checking the seconds, since they default to 0 if // missing if (varname == "date") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return -1; return !core::Record::downcast(*self->rec).get_datetime().is_missing(); } else if (varname == "datemin") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return -1; return !core::Record::downcast(*self->rec).get_datetimerange().min.is_missing(); } else if (varname == "datemax") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return -1; return !core::Record::downcast(*self->rec).get_datetimerange().max.is_missing(); } break; case 'l': if (varname == "level") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return -1; return any_key_set(*self->rec, level_keys, 4); } break; case 't': if (varname == "trange" || varname == "timerange") { if (PyErr_WarnEx(PyExc_DeprecationWarning, "date, datemin, datemax, level, trange, and timerange may disappear as record keys in a future version of DB-All.e; no replacement is planned", 1)) return -1; return any_key_set(*self->rec, trange_keys, 3); } break; } return self->rec->isset(varname.c_str()) ? 1 : 0; } static PyObject* dpy_Record_copy(dpy_Record* self) { dpy_Record* result = PyObject_New(dpy_Record, &dpy_Record_Type); if (!result) return NULL; try { result->rec = self->rec->clone().release(); result->station_context = self->station_context; return (PyObject*)result; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Record_clear(dpy_Record* self) { try { self->rec->clear(); self->station_context = false; Py_RETURN_NONE; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Record_clear_vars(dpy_Record* self) { try { self->rec->clear_vars(); Py_RETURN_NONE; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Record_keys(dpy_Record* self) { pyo_unique_ptr result(PyList_New(0)); if (!result) return nullptr; try { bool fail = false; self->rec->foreach_key([&](const char* key, const wreport::Var&) { if (fail) return; pyo_unique_ptr item(PyUnicode_FromString(key)); if (!item) { fail = true; return; } if (PyList_Append(result, item)) { fail = true; return; } }); return result.release(); } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Record_items(dpy_Record* self) { pyo_unique_ptr result(PyList_New(0)); if (!result) return nullptr; try { bool fail = false; self->rec->foreach_key([&](const char* key, const wreport::Var& val) { if (fail) return; pyo_unique_ptr py_key(PyUnicode_FromString(key)); if (!py_key) { fail = true; return; } pyo_unique_ptr py_val(wrpy->var_value_to_python(val)); if (!py_val) { fail = true; return; } pyo_unique_ptr item(PyTuple_Pack(2, py_key.get(), py_val.get())); if (!item) { fail = true; return; } if (PyList_Append(result, item)) { fail = true; return; } }); return result.release(); } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Record_varitems(dpy_Record* self) { pyo_unique_ptr result(PyList_New(0)); if (!result) return nullptr; try { bool fail = false; self->rec->foreach_key([&](const char* key, const wreport::Var& val) { if (fail) return; pyo_unique_ptr py_key(PyUnicode_FromString(key)); if (!py_key) { fail = true; return; } pyo_unique_ptr py_val((PyObject*)wrpy->var_create_copy(val)); if (!py_val) { fail = true; return; } pyo_unique_ptr item(PyTuple_Pack(2, py_key.get(), py_val.get())); if (!item) { fail = true; return; } if (PyList_Append(result, item)) { fail = true; return; } }); return result.release(); } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Record_var(dpy_Record* self, PyObject* args) { const char* name = NULL; if (!PyArg_ParseTuple(args, "s", &name)) return nullptr; try { return (PyObject*)wrpy->var_create_copy((*self->rec)[name]); } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Record_key(dpy_Record* self, PyObject* args) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "please use Record.var(name) instead of Record.key(name)", 1)) return nullptr; const char* name = NULL; if (!PyArg_ParseTuple(args, "s", &name)) return nullptr; try { return (PyObject*)wrpy->var_create_copy((*self->rec)[name]); } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Record_update(dpy_Record* self, PyObject *args, PyObject *kw) { if (kw) { PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(kw, &pos, &key, &value)) if (dpy_Record_setitem(self, key, value) < 0) return NULL; } Py_RETURN_NONE; } static PyObject* dpy_Record_get(dpy_Record* self, PyObject *args, PyObject* kw) { static char* kwlist[] = { "key", "default", NULL }; PyObject* key; PyObject* def = Py_None; if (!PyArg_ParseTupleAndKeywords(args, kw, "O|O", kwlist, &key, &def)) return nullptr; try { int has = dpy_Record_contains(self, key); if (has < 0) return NULL; if (!has) { Py_INCREF(def); return def; } return dpy_Record_getitem(self, key); } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Record_vars(dpy_Record* self) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "Record.vars() may disappear in a future version of DB-All.e, and no replacement is planned", 1)) return nullptr; const std::vector& vars = core::Record::downcast(*self->rec).vars(); pyo_unique_ptr result(PyTuple_New(vars.size())); if (!result) return NULL; try { for (size_t i = 0; i < vars.size(); ++i) { pyo_unique_ptr v((PyObject*)wrpy->var_create_copy(*vars[i])); if (!v) return nullptr; if (PyTuple_SetItem(result, i, v.release())) return nullptr; } return result.release(); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyObject* dpy_Record_date_extremes(dpy_Record* self) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "Record.date_extremes may disappear in a future version of DB-All.e, and no replacement is planned", 1)) return NULL; try { DatetimeRange dtr = core::Record::downcast(*self->rec).get_datetimerange(); pyo_unique_ptr dt_min(datetime_to_python(dtr.min)); pyo_unique_ptr dt_max(datetime_to_python(dtr.max)); if (!dt_min || !dt_max) return NULL; return Py_BuildValue("(NN)", dt_min.release(), dt_max.release()); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyObject* dpy_Record_set_station_context(dpy_Record* self) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "Record.set_station_context is deprecated in favour of using DB.query_station_data", 1)) return NULL; try { self->rec->set_datetime(Datetime()); self->rec->set_level(Level()); self->rec->set_trange(Trange()); self->station_context = true; Py_RETURN_NONE; } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyObject* dpy_Record_set_from_string(dpy_Record* self, PyObject *args) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "Record.set_from_string() may disappear in a future version of DB-All.e, and no replacement is planned", 1)) return nullptr; const char* str = NULL; if (!PyArg_ParseTuple(args, "s", &str)) return NULL; try { core::Record::downcast(*self->rec).set_from_string(str); self->station_context = false; Py_RETURN_NONE; } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyMethodDef dpy_Record_methods[] = { {"copy", (PyCFunction)dpy_Record_copy, METH_NOARGS, "return a deep copy of the Record" }, {"clear", (PyCFunction)dpy_Record_clear, METH_NOARGS, "remove all data from the record" }, {"clear_vars", (PyCFunction)dpy_Record_clear_vars, METH_NOARGS, "remove all variables from the record, leaving the keywords intact" }, {"keys", (PyCFunction)dpy_Record_keys, METH_NOARGS, "return a list with all the keys set in the Record." }, {"items", (PyCFunction)dpy_Record_items, METH_NOARGS, "return a list with all the (key, value) tuples set in the Record." }, {"varitems", (PyCFunction)dpy_Record_varitems, METH_NOARGS, "return a list with all the (key, `dballe.Var`_) tuples set in the Record." }, {"var", (PyCFunction)dpy_Record_var, METH_VARARGS, "return a `dballe.Var`_ from the record, given its key." }, {"update", (PyCFunction)dpy_Record_update, METH_VARARGS | METH_KEYWORDS, "set many record keys/vars in a single shot, via kwargs" }, {"get", (PyCFunction)dpy_Record_get, METH_VARARGS | METH_KEYWORDS, "lookup a value, returning a fallback value (None by default) if unset" }, // Deprecated {"key", (PyCFunction)dpy_Record_var, METH_VARARGS, "(deprecated) return a `dballe.Var`_ from the record, given its key." }, {"vars", (PyCFunction)dpy_Record_vars, METH_NOARGS, "(deprecated) return a sequence with all the variables set on the Record. Note that this does not include keys." }, {"date_extremes", (PyCFunction)dpy_Record_date_extremes, METH_NOARGS, "(deprecated) get two datetime objects with the lower and upper bounds of the datetime period in this record" }, {"set_station_context", (PyCFunction)dpy_Record_set_station_context, METH_NOARGS, "(deprecated) set the date, level and time range values to match the station data context" }, {"set_from_string", (PyCFunction)dpy_Record_set_from_string, METH_VARARGS, "(deprecated) set values from a 'key=val' string" }, {NULL} }; static int dpy_Record_init(dpy_Record* self, PyObject* args, PyObject* kw) { // Construct on preallocated memory self->rec = Record::create().release(); self->station_context = false; if (kw) { PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(kw, &pos, &key, &value)) if (dpy_Record_setitem(self, key, value) < 0) return -1; } return 0; } static void dpy_Record_dealloc(dpy_Record* self) { delete self->rec; self->rec = 0; } static PyObject* dpy_Record_str(dpy_Record* self) { /* std::string f = self->var.format("None"); return PyString_FromString(f.c_str()); */ return PyUnicode_FromString("Record"); } static PyObject* dpy_Record_repr(dpy_Record* self) { /* string res = "Var('"; res += varcode_format(self->var.code()); if (self->var.info()->is_string()) { res += "', '"; res += self->var.format(); res += "')"; } else { res += "', "; res += self->var.format("None"); res += ")"; } return PyString_FromString(res.c_str()); */ return PyUnicode_FromString("Record object"); } static PySequenceMethods dpy_Record_sequence = { 0, // sq_length 0, // sq_concat 0, // sq_repeat 0, // sq_item 0, // sq_slice 0, // sq_ass_item 0, // sq_ass_slice (objobjproc)dpy_Record_contains, // sq_contains }; static PyMappingMethods dpy_Record_mapping = { 0, // __len__ (binaryfunc)dpy_Record_getitem, // __getitem__ (objobjargproc)dpy_Record_setitem, // __setitem__ }; static PyObject* dpy_Record_iter(dpy_Record* self) { pyo_unique_ptr keys(dpy_Record_keys(self)); if (!keys) return nullptr; pyo_unique_ptr iter(PyObject_GetIter(keys)); if (!iter) return nullptr; return iter.release(); } static PyObject* dpy_Record_richcompare(dpy_Record* a, dpy_Record* b, int op) { PyObject *result; // Make sure both arguments are Records. if (!(dpy_Record_Check(a) && dpy_Record_Check(b))) { result = Py_NotImplemented; goto out; } int cmp; switch (op) { case Py_EQ: cmp = *a->rec == *b->rec; break; case Py_NE: cmp = *a->rec != *b->rec; break; default: // https://www.python.org/dev/peps/pep-0207/ // If the function cannot compare the particular combination of objects, it // should return a new reference to Py_NotImplemented. result = Py_NotImplemented; goto out; } result = cmp ? Py_True : Py_False; out: Py_INCREF(result); return result; } PyTypeObject dpy_Record_Type = { PyVarObject_HEAD_INIT(NULL, 0) "dballe.Record", // tp_name sizeof(dpy_Record), // tp_basicsize 0, // tp_itemsize (destructor)dpy_Record_dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare (reprfunc)dpy_Record_repr, // tp_repr 0, // tp_as_number &dpy_Record_sequence, // tp_as_sequence &dpy_Record_mapping, // tp_as_mapping 0, // tp_hash 0, // tp_call (reprfunc)dpy_Record_str, // tp_str 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, // tp_flags R"( A record holds a number of key->value mappings, similar to a dict. Keys are strings, from a fixed set of keywords defined in DB-All.e and documented in the Fortran API documentation, plus all varcodes from the DB-All.e BUFR/CREX B table. Using unknown keys raises an exception. Values are values internally stored inside `dballe.Var`_ objects, with a `dballe.Varinfo`_ corresponding to the key. Record's mapping interface directly exposes the variable values, but the `dballe.Var`_ objects are still accessible using Record.var(key). A Record is used to make queries to the database, and read results. When creating a new record, keyword arguments can be passed and they are set as if Record.update(\*\*kwargs) had been called. When setting items, either via __setitem__ and via update(), there are special keys that allow to set many items in a single call:: # Set year, month, day, hour, min, sec rec["datetime"] = None rec["datetime"] = datetime.datetime(2015, 06, 21, 12, 0, 0) # Set yearmin..secmin and yearmax..secmax rec["datetime"] = (None, None) rec["datetime"] = (datetime.datetime(2014), None) rec["datetime"] = (None, datetime.datetime(2015)) rec["datetime"] = (datetime.datetime(2014), datetime.datetime(2015)) # Set leveltype1, l1, leveltype2, l2 rec["level"] = None rec["level"] = (103, 2000) rec["level"] = (103, 2000, 103, 10000) # Set pindicator, p1, p2 rec["trange"] = None rec["trange"] = (205, 0, 10800) Examples:: rec = Record(lat=44.05, lon=11.03, B12101=22.1) # Key lookup returns the value of the corresponding variable print(rec["lat"], rec["B12101"]) # Use .var() to get the variable itself; note that it can return # None if the value is not set print(rec.var("lat").info.desc, rec.var("B12101").info.desc) # Iterating a record iterates all keys for key in rec: print(key, rec.get(key, "undefined"), rec.var(key).info.desc) # Use .vars() to get a list of only the varcode keys for varcode in rec.vars(): print(varcode, rec.get(varcode, "undefined"), rec.var(varcode).info.desc) )", // tp_doc 0, // tp_traverse 0, // tp_clear (richcmpfunc)dpy_Record_richcompare, // tp_richcompare 0, // tp_weaklistoffset (getiterfunc)dpy_Record_iter, // tp_iter 0, // tp_iternext dpy_Record_methods, // tp_methods 0, // tp_members 0, // tp_getset 0, // tp_base 0, // tp_dict 0, // tp_descr_get 0, // tp_descr_set 0, // tp_dictoffset (initproc)dpy_Record_init, // tp_init 0, // tp_alloc 0, // tp_new }; } namespace dballe { namespace python { dpy_Record* record_create() { return (dpy_Record*)PyObject_CallObject((PyObject*)&dpy_Record_Type, NULL); } void register_record(PyObject* m) { common_init(); dpy_Record_Type.tp_new = PyType_GenericNew; if (PyType_Ready(&dpy_Record_Type) < 0) return; Py_INCREF(&dpy_Record_Type); PyModule_AddObject(m, "Record", (PyObject*)&dpy_Record_Type); } } } dballe-7.7/python/test-rconvert.py0000755000175000017500000000420012652630043014245 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import dballe from dballe import volnd, rconvert import numpy, rpy2 from datetime import * import unittest class TestR(unittest.TestCase): def setUp(self): from testlib import fill_volnd numpy.seterr(divide="raise", over="raise", under="raise", invalid="raise") self.db = dballe.DB.connect_test() fill_volnd(self.db) #def f(x,y,z): # return (x+1)*100+(y+1)*10+(z+1) #a = MA.array(numpy.fromfunction(f, (4,3,2))) ##a = MA.array(numpy.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], dtype='int8')) #a[1,1,1]=MA.masked #print "verypre", a ##rconvert.makeConvertible(a) #rpy.r.print_(rconvert.ma_to_r(a, dimnames=[['a','b','c','d'],['e','f','g'],['h', 'i']])) def test_volnd(self): # Test from volnd query = dballe.Record(datetime=datetime(2007, 1, 1, 0, 0, 0)) #query.set("var", "B10004") #query.settimerange(dballe.TimeRange(0,0,0)) vars = volnd.read(self.db.query_data(query), (volnd.AnaIndex(), volnd.NetworkIndex(), volnd.LevelIndex(), volnd.TimeRangeIndex())) #print "ana:", vars["B10004"].dims[0] #print "net:", vars["B10004"].dims[1] #print vars["B10004"] #rpy.r.print_(rconvert.vnddata_to_r(vars['B10004'])) #rpy.r.assign('pippo', rconvert.vnddata_to_r(vars['B10004'])) #rpy.r.save('pippo', file='/tmp/pippo') rconvert.volnd_save_to_r(vars, "/tmp/pippo") def test_bug1(self): # Second test case reported by Paolo query = dballe.Record() #query.setd("latmin", 10.) #query.setd("latmax", 60.) #query.setd("lonmin", -10.) #query.setd("lonmax", 40.) query["var"] = "B13011" vars = volnd.read(self.db.query_data(query), (volnd.AnaIndex(),volnd.DateTimeIndex()), checkConflicts=False) rconvert.volnd_save_to_r(vars, "/tmp/pippo") if __name__ == "__main__": from testlib import main main("test_rconvert") dballe-7.7/python/db.cc0000644000175000017500000007205612652630043011763 00000000000000#include #include "db.h" #include "record.h" #include "cursor.h" #include "common.h" #include "dballe/types.h" #include "dballe/file.h" #include "dballe/core/query.h" #include "dballe/core/values.h" #include "dballe/message.h" #include "dballe/msg/codec.h" #include #include #include "config.h" #if PY_MAJOR_VERSION >= 3 #define PyInt_FromLong PyLong_FromLong #define PyInt_AsLong PyLong_AsLong #define PyInt_Check PyLong_Check #define PyInt_Type PyLong_Type #define Py_TPFLAGS_HAVE_ITER 0 #endif using namespace std; using namespace dballe; using namespace dballe::python; using namespace wreport; template static PyObject* get_insert_ids(const Vals& vals) { pyo_unique_ptr res(PyDict_New()); pyo_unique_ptr ana_id(PyInt_FromLong(vals.info.ana_id)); if (!ana_id) return nullptr; if (PyDict_SetItemString(res, "ana_id", ana_id)) return nullptr; for (const auto& v: vals.values) { pyo_unique_ptr id(PyInt_FromLong(v.second.data_id)); pyo_unique_ptr varcode(format_varcode(v.first)); if (PyDict_SetItem(res, varcode, id)) return nullptr; } return res.release(); } extern "C" { static PyGetSetDef dpy_DB_getsetters[] = { //{"code", (getter)dpy_Var_code, NULL, "variable code", NULL }, //{"isset", (getter)dpy_Var_isset, NULL, "true if the value is set", NULL }, {NULL} }; static PyObject* dpy_DB_connect(PyTypeObject *type, PyObject *args, PyObject* kw) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "please use DB.connect_from_url instead of DB.connect", 1)) return NULL; static const char* kwlist[] = { "dsn", "user", "password", NULL }; const char* dsn; const char* user = ""; const char* pass = ""; if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ss", const_cast(kwlist), &dsn, &user, &pass)) return NULL; unique_ptr db; try { db = DB::connect(dsn, user, pass); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } return (PyObject*)db_create(move(db)); } static PyObject* dpy_DB_connect_from_file(PyTypeObject *type, PyObject *args) { const char* fname; if (!PyArg_ParseTuple(args, "s", &fname)) return NULL; unique_ptr db; try { db = DB::connect_from_file(fname); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } return (PyObject*)db_create(move(db)); } static PyObject* dpy_DB_connect_from_url(PyTypeObject *type, PyObject *args) { const char* url; if (!PyArg_ParseTuple(args, "s", &url)) return NULL; unique_ptr db; try { db = DB::connect_from_url(url); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } return (PyObject*)db_create(move(db)); } static PyObject* dpy_DB_connect_test(PyTypeObject *type) { unique_ptr db; try { db = DB::connect_test(); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } return (PyObject*)db_create(move(db)); } static PyObject* dpy_DB_is_url(PyTypeObject *type, PyObject *args) { const char* url; if (!PyArg_ParseTuple(args, "s", &url)) return NULL; if (DB::is_url(url)) Py_RETURN_TRUE; else Py_RETURN_FALSE; } static PyObject* dpy_DB_reset(dpy_DB* self, PyObject *args) { const char* repinfo_file = 0; if (!PyArg_ParseTuple(args, "|s", &repinfo_file)) return NULL; try { self->db->reset(repinfo_file); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } Py_RETURN_NONE; } /* virtual void update_repinfo(const char* repinfo_file, int* added, int* deleted, int* updated) = 0; */ static PyObject* dpy_DB_insert(dpy_DB* self, PyObject* args, PyObject* kw) { static const char* kwlist[] = { "record", "can_replace", "can_add_stations", NULL }; dpy_Record* record; int can_replace = 0; int station_can_add = 0; if (PyErr_WarnEx(PyExc_DeprecationWarning, "please use DB.insert_station_data or DB.insert_data instead of DB.insert", 1)) return NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, "O!|ii", const_cast(kwlist), &dpy_Record_Type, &record, &can_replace, &station_can_add)) return NULL; try { if (record->station_context) { StationValues vals(*record->rec); self->db->insert_station_data(vals, can_replace, station_can_add); } else { DataValues vals(*record->rec); self->db->insert_data(vals, can_replace, station_can_add); } Py_RETURN_NONE; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_insert_station_data(dpy_DB* self, PyObject* args, PyObject* kw) { static const char* kwlist[] = { "record", "can_replace", "can_add_stations", NULL }; dpy_Record* record; int can_replace = 0; int station_can_add = 0; if (!PyArg_ParseTupleAndKeywords(args, kw, "O!|ii", const_cast(kwlist), &dpy_Record_Type, &record, &can_replace, &station_can_add)) return NULL; try { StationValues vals(*record->rec); self->db->insert_station_data(vals, can_replace, station_can_add); return get_insert_ids(vals); } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_insert_data(dpy_DB* self, PyObject* args, PyObject* kw) { static const char* kwlist[] = { "record", "can_replace", "can_add_stations", NULL }; dpy_Record* record; int can_replace = 0; int station_can_add = 0; if (!PyArg_ParseTupleAndKeywords(args, kw, "O!|ii", const_cast(kwlist), &dpy_Record_Type, &record, &can_replace, &station_can_add)) return NULL; try { DataValues vals(*record->rec); self->db->insert_data(vals, can_replace, station_can_add); return get_insert_ids(vals); } DBALLE_CATCH_RETURN_PYO } static unsigned db_load_file_enc(DB* db, File::Encoding encoding, FILE* file, bool close_on_exit, const std::string& name) { std::unique_ptr f = File::create(encoding, file, close_on_exit, name); std::unique_ptr imp = msg::Importer::create(f->encoding()); unsigned count = 0; f->foreach([&](const BinaryMessage& raw) { Messages msgs = imp->from_binary(raw); db->import_msgs(msgs, NULL, 0); ++count; return true; }); return count; } static unsigned db_load_file(DB* db, FILE* file, bool close_on_exit, const std::string& name) { std::unique_ptr f = File::create(file, close_on_exit, name); std::unique_ptr imp = msg::Importer::create(f->encoding()); unsigned count = 0; f->foreach([&](const BinaryMessage& raw) { Messages msgs = imp->from_binary(raw); db->import_msgs(msgs, NULL, 0); ++count; return true; }); return count; } static PyObject* dpy_DB_load(dpy_DB* self, PyObject* args) { PyObject* obj; const char* encoding = nullptr; if (!PyArg_ParseTuple(args, "O|s", &obj, &encoding)) return nullptr; string repr; if (object_repr(obj, repr)) return nullptr; try { int fileno = file_get_fileno(obj); if (fileno == -1) { if (PyErr_Occurred()) return nullptr; char* buf; Py_ssize_t len; pyo_unique_ptr data = file_get_data(obj, buf, len); if (!data) return nullptr; FILE* f = fmemopen(buf, len, "r"); if (!f) return nullptr; unsigned count; if (encoding) { count = db_load_file_enc(self->db, File::parse_encoding(encoding), f, true, repr); } else count = db_load_file(self->db, f, true, repr); return PyInt_FromLong(count); } else { // Duplicate the file descriptor because both python and libc will want to // close it fileno = dup(fileno); if (fileno == -1) { PyErr_Format(PyExc_OSError, "cannot dup() the file handle from %s", repr.c_str()); return nullptr; } FILE* f = fdopen(fileno, "rb"); if (f == nullptr) { close(fileno); PyErr_Format(PyExc_OSError, "cannot fdopen() the dup()ed file handle from %s", repr.c_str()); return nullptr; } unsigned count; if (encoding) { count = db_load_file_enc(self->db, File::parse_encoding(encoding), f, true, repr); } else count = db_load_file(self->db, f, true, repr); return PyInt_FromLong(count); } } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyObject* dpy_DB_remove_station_data(dpy_DB* self, PyObject* args) { dpy_Record* record; if (!PyArg_ParseTuple(args, "O!", &dpy_Record_Type, &record)) return NULL; // TODO: if it is a dict, turn it directly into a Query? try { core::Query query; query.set_from_record(*record->rec); self->db->remove_station_data(query); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } Py_RETURN_NONE; } static PyObject* dpy_DB_remove(dpy_DB* self, PyObject* args) { dpy_Record* record; if (!PyArg_ParseTuple(args, "O!", &dpy_Record_Type, &record)) return NULL; // TODO: if it is a dict, turn it directly into a Query? try { core::Query query; query.set_from_record(*record->rec); if (record->station_context) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "DB.remove after Record.set_station_context is deprecated in favour of using DB.remove_station_data", 1)) return NULL; self->db->remove_station_data(query); } else self->db->remove(query); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } Py_RETURN_NONE; } static PyObject* dpy_DB_disappear(dpy_DB* self) { try { self->db->disappear(); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } Py_RETURN_NONE; } static PyObject* dpy_DB_vacuum(dpy_DB* self) { try { self->db->vacuum(); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } Py_RETURN_NONE; } static PyObject* dpy_DB_query_stations(dpy_DB* self, PyObject* args) { dpy_Record* record; if (!PyArg_ParseTuple(args, "O!", &dpy_Record_Type, &record)) return NULL; // TODO: if it is a dict, turn it directly into a Query? try { core::Query query; query.set_from_record(*record->rec); std::unique_ptr res = self->db->query_stations(query); return (PyObject*)cursor_create(self, move(res)); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyObject* dpy_DB_query_data(dpy_DB* self, PyObject* args) { dpy_Record* record; if (!PyArg_ParseTuple(args, "O!", &dpy_Record_Type, &record)) return NULL; // TODO: if it is a dict, turn it directly into a Query? //self->db->dump(stderr); try { core::Query query; query.set_from_record(*record->rec); std::unique_ptr res; if (record->station_context) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "DB.query_data after Record.set_station_context is deprecated in favour of using DB.query_station_data", 1)) return NULL; res = self->db->query_station_data(query); } else res = self->db->query_data(query); return (PyObject*)cursor_create(self, move(res)); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyObject* dpy_DB_query_station_data(dpy_DB* self, PyObject* args) { dpy_Record* record; if (!PyArg_ParseTuple(args, "O!", &dpy_Record_Type, &record)) return NULL; // TODO: if it is a dict, turn it directly into a Query? try { core::Query query; query.set_from_record(*record->rec); std::unique_ptr res = self->db->query_station_data(query); return (PyObject*)cursor_create(self, move(res)); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyObject* dpy_DB_query_summary(dpy_DB* self, PyObject* args) { dpy_Record* record; if (!PyArg_ParseTuple(args, "O!", &dpy_Record_Type, &record)) return NULL; // TODO: if it is a dict, turn it directly into a Query? try { core::Query query; query.set_from_record(*record->rec); std::unique_ptr res = self->db->query_summary(query); return (PyObject*)cursor_create(self, move(res)); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyObject* dpy_DB_query_attrs(dpy_DB* self, PyObject* args, PyObject* kw) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "please use DB.attr_query_station or DB.attr_query_data instead of DB.query_attrs", 1)) return NULL; static const char* kwlist[] = { "varcode", "reference_id", "attrs", NULL }; int reference_id; const char* varname; PyObject* attrs = 0; if (!PyArg_ParseTupleAndKeywords(args, kw, "si|O", const_cast(kwlist), &varname, &reference_id, &attrs)) return NULL; // Read the attribute list, if provided db::AttrList codes; if (db_read_attrlist(attrs, codes)) return NULL; self->attr_rec->rec->clear(); try { wreport::Varcode varcode = resolve_varcode(varname); if (self->db->is_station_variable(reference_id, varcode)) self->db->attr_query_station(reference_id, [&](unique_ptr&& var) { if (!codes.empty() && find(codes.begin(), codes.end(), var->code()) == codes.end()) return; self->attr_rec->rec->set(move(var)); }); else self->db->attr_query_data(reference_id, [&](unique_ptr&& var) { if (!codes.empty() && find(codes.begin(), codes.end(), var->code()) == codes.end()) return; self->attr_rec->rec->set(move(var)); }); Py_INCREF(self->attr_rec); return (PyObject*)self->attr_rec; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_attr_query_station(dpy_DB* self, PyObject* args) { int reference_id; if (!PyArg_ParseTuple(args, "i", &reference_id)) return NULL; self->attr_rec->rec->clear(); try { self->db->attr_query_station(reference_id, [&](unique_ptr var) { self->attr_rec->rec->set(move(var)); }); Py_INCREF(self->attr_rec); return (PyObject*)self->attr_rec; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_attr_query_data(dpy_DB* self, PyObject* args) { int reference_id; if (!PyArg_ParseTuple(args, "i", &reference_id)) return NULL; self->attr_rec->rec->clear(); try { self->db->attr_query_data(reference_id, [&](unique_ptr&& var) { self->attr_rec->rec->set(move(var)); }); Py_INCREF(self->attr_rec); return (PyObject*)self->attr_rec; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_attr_insert(dpy_DB* self, PyObject* args, PyObject* kw) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "please use DB.attr_insert_station or DB.attr_insert_data instead of DB.attr_insert", 1)) return NULL; static const char* kwlist[] = { "varcode", "attrs", "reference_id", NULL }; int reference_id = -1; const char* varname; dpy_Record* record; if (!PyArg_ParseTupleAndKeywords(args, kw, "sO!|i", const_cast(kwlist), &varname, &dpy_Record_Type, &record, &reference_id)) return NULL; if (reference_id == -1) { PyErr_SetString(PyExc_ValueError, "please provide a reference_id argument: implicitly reusing the one from the last insert is not supported anymore"); return NULL; } try { if (self->db->is_station_variable(reference_id, resolve_varcode(varname))) self->db->attr_insert_data(reference_id, *record->rec); else self->db->attr_insert_data(reference_id, *record->rec); Py_RETURN_NONE; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_attr_insert_station(dpy_DB* self, PyObject* args) { int data_id; dpy_Record* attrs; if (!PyArg_ParseTuple(args, "iO!", &data_id, &dpy_Record_Type, &attrs)) return NULL; try { self->db->attr_insert_station(data_id, *attrs->rec); Py_RETURN_NONE; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_attr_insert_data(dpy_DB* self, PyObject* args) { int data_id; dpy_Record* attrs; if (!PyArg_ParseTuple(args, "iO!", &data_id, &dpy_Record_Type, &attrs)) return NULL; try { self->db->attr_insert_data(data_id, *attrs->rec); Py_RETURN_NONE; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_attr_remove(dpy_DB* self, PyObject* args, PyObject* kw) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "please use DB.attr_remove_station or DB.attr_remove_data instead of DB.attr_remove", 1)) return NULL; static const char* kwlist[] = { "varcode", "reference_id", "attrs", NULL }; int reference_id; const char* varname; PyObject* attrs = 0; if (!PyArg_ParseTupleAndKeywords(args, kw, "si|O", const_cast(kwlist), &varname, &reference_id, &attrs)) return NULL; // Read the attribute list, if provided db::AttrList codes; if (db_read_attrlist(attrs, codes)) return NULL; try { if (self->db->is_station_variable(reference_id, resolve_varcode(varname))) self->db->attr_remove_station(reference_id, codes); else self->db->attr_remove_data(reference_id, codes); Py_RETURN_NONE; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_attr_remove_station(dpy_DB* self, PyObject* args) { int reference_id; PyObject* attrs = 0; if (!PyArg_ParseTuple(args, "i|O", &reference_id, &attrs)) return NULL; // Read the attribute list, if provided db::AttrList codes; if (db_read_attrlist(attrs, codes)) return NULL; try { self->db->attr_remove_station(reference_id, codes); Py_RETURN_NONE; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_attr_remove_data(dpy_DB* self, PyObject* args) { int reference_id; PyObject* attrs = 0; if (!PyArg_ParseTuple(args, "i|O", &reference_id, &attrs)) return NULL; // Read the attribute list, if provided db::AttrList codes; if (db_read_attrlist(attrs, codes)) return NULL; try { self->db->attr_remove_data(reference_id, codes); Py_RETURN_NONE; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_DB_export_to_file(dpy_DB* self, PyObject* args, PyObject* kw) { static const char* kwlist[] = { "query", "format", "filename", "generic", NULL }; dpy_Record* query; const char* format; const char* filename; int as_generic = 0; if (!PyArg_ParseTupleAndKeywords(args, kw, "O!ss|i", const_cast(kwlist), &dpy_Record_Type, &query, &format, &filename, &as_generic)) return NULL; File::Encoding encoding = File::BUFR; if (strcmp(format, "BUFR") == 0) encoding = File::BUFR; else if (strcmp(format, "CREX") == 0) encoding = File::CREX; else { PyErr_SetString(PyExc_ValueError, "encoding must be one of BUFR or CREX"); return NULL; } try { std::unique_ptr out = File::create(encoding, filename, "wb"); msg::Exporter::Options opts; if (as_generic) opts.template_name = "generic"; auto exporter = msg::Exporter::create(out->encoding(), opts); auto q = Query::create(); q->set_from_record(*query->rec); self->db->export_msgs(*q, [&](unique_ptr&& msg) { Messages msgs; msgs.append(move(msg)); out->write(exporter->to_binary(msgs)); return true; }); Py_RETURN_NONE; } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } static PyMethodDef dpy_DB_methods[] = { {"connect", (PyCFunction)dpy_DB_connect, METH_VARARGS | METH_KEYWORDS | METH_CLASS, "(deprecated) Create a DB connecting to an ODBC source" }, {"connect_from_file", (PyCFunction)dpy_DB_connect_from_file, METH_VARARGS | METH_CLASS, "Create a DB connecting to a SQLite file" }, {"connect_from_url", (PyCFunction)dpy_DB_connect_from_url, METH_VARARGS | METH_CLASS, "Create a DB as defined in an URL-like string" }, {"connect_test", (PyCFunction)dpy_DB_connect_test, METH_NOARGS | METH_CLASS, "Create a DB for running the test suite, as configured in the test environment" }, {"is_url", (PyCFunction)dpy_DB_is_url, METH_VARARGS | METH_CLASS, "Checks if a string looks like a DB url" }, {"disappear", (PyCFunction)dpy_DB_disappear, METH_NOARGS, "Remove all our traces from the database, if applicable." }, {"reset", (PyCFunction)dpy_DB_reset, METH_VARARGS, "Reset the database, removing all existing Db-All.e tables and re-creating them empty." }, {"insert", (PyCFunction)dpy_DB_insert, METH_VARARGS | METH_KEYWORDS, "(deprecated)Insert a record in the database" }, {"insert_station_data", (PyCFunction)dpy_DB_insert_station_data, METH_VARARGS | METH_KEYWORDS, "Insert station values in the database" }, {"insert_data", (PyCFunction)dpy_DB_insert_data, METH_VARARGS | METH_KEYWORDS, "Insert data values in the database" }, {"load", (PyCFunction)dpy_DB_load, METH_VARARGS, R"( load(fp, encoding=None) Load a file object in the database. An encoding can optionally be provided as a string ("BUFR", "CREX", "AOF"). If encoding is None then load will try to autodetect based on the first byte of the file. )" }, {"remove_station_data", (PyCFunction)dpy_DB_remove_station_data, METH_VARARGS, "Remove station variables from the database" }, {"remove", (PyCFunction)dpy_DB_remove, METH_VARARGS, "Remove variables from the database" }, {"vacuum", (PyCFunction)dpy_DB_vacuum, METH_NOARGS, "Perform database cleanup operations" }, {"query_stations", (PyCFunction)dpy_DB_query_stations, METH_VARARGS, "Query the station archive in the database; returns a Cursor" }, {"query_station_data", (PyCFunction)dpy_DB_query_station_data, METH_VARARGS, "Query the station variables in the database; returns a Cursor" }, {"query_data", (PyCFunction)dpy_DB_query_data, METH_VARARGS, "Query the variables in the database; returns a Cursor" }, {"query_summary", (PyCFunction)dpy_DB_query_summary, METH_VARARGS, "Query the summary of the results of a query; returns a Cursor" }, {"query_attrs", (PyCFunction)dpy_DB_query_attrs, METH_VARARGS | METH_KEYWORDS, "Query attributes" }, {"attr_query_station", (PyCFunction)dpy_DB_attr_query_station, METH_VARARGS, "Query attributes" }, {"attr_query_data", (PyCFunction)dpy_DB_attr_query_data, METH_VARARGS, "Query attributes" }, {"attr_insert", (PyCFunction)dpy_DB_attr_insert, METH_VARARGS | METH_KEYWORDS, "Insert new attributes into the database" }, {"attr_insert_station", (PyCFunction)dpy_DB_attr_insert_station, METH_VARARGS, "Insert new attributes into the database" }, {"attr_insert_data", (PyCFunction)dpy_DB_attr_insert_data, METH_VARARGS, "Insert new attributes into the database" }, {"attr_remove", (PyCFunction)dpy_DB_attr_remove, METH_VARARGS | METH_KEYWORDS, "Remove attributes" }, {"attr_remove_station", (PyCFunction)dpy_DB_attr_remove_station, METH_VARARGS, "Remove attributes" }, {"attr_remove_data", (PyCFunction)dpy_DB_attr_remove_data, METH_VARARGS, "Remove attributes" }, {"export_to_file", (PyCFunction)dpy_DB_export_to_file, METH_VARARGS | METH_KEYWORDS, "Export data matching a query as bulletins to a named file" }, {NULL} }; static int dpy_DB_init(dpy_DB* self, PyObject* args, PyObject* kw) { // People should not invoke DB() as a constructor, but if they do, // this is better than a segfault later on PyErr_SetString(PyExc_NotImplementedError, "DB objects cannot be constructed explicitly"); return -1; } static void dpy_DB_dealloc(dpy_DB* self) { if (self->db) delete self->db; } static PyObject* dpy_DB_str(dpy_DB* self) { /* std::string f = self->var.format("None"); return PyUnicode_FromString(f.c_str()); */ return PyUnicode_FromString("DB"); } static PyObject* dpy_DB_repr(dpy_DB* self) { /* string res = "Var('"; res += varcode_format(self->var.code()); if (self->var.info()->is_string()) { res += "', '"; res += self->var.format(); res += "')"; } else { res += "', "; res += self->var.format("None"); res += ")"; } return PyUnicode_FromString(res.c_str()); */ return PyUnicode_FromString("DB object"); } PyTypeObject dpy_DB_Type = { PyVarObject_HEAD_INIT(NULL, 0) "dballe.DB", // tp_name sizeof(dpy_DB), // tp_basicsize 0, // tp_itemsize (destructor)dpy_DB_dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare (reprfunc)dpy_DB_repr, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping 0, // tp_hash 0, // tp_call (reprfunc)dpy_DB_str, // tp_str 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags "DB-All.e DB", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext dpy_DB_methods, // tp_methods 0, // tp_members dpy_DB_getsetters, // tp_getset 0, // tp_base 0, // tp_dict 0, // tp_descr_get 0, // tp_descr_set 0, // tp_dictoffset (initproc)dpy_DB_init, // tp_init 0, // tp_alloc 0, // tp_new }; } namespace dballe { namespace python { int db_read_attrlist(PyObject* attrs, db::AttrList& codes) { if (!attrs) return 0; pyo_unique_ptr iter(PyObject_GetIter(attrs)); if (!iter) return -1; try { while (PyObject* iter_item = PyIter_Next(iter)) { pyo_unique_ptr item(iter_item); string name; if (string_from_python(item, name)) return -1; codes.push_back(resolve_varcode(name)); } return 0; } DBALLE_CATCH_RETURN_INT } dpy_DB* db_create(std::unique_ptr db) { dpy_Record* attr_rec = record_create(); if (!attr_rec) return NULL; dpy_DB* result = PyObject_New(dpy_DB, &dpy_DB_Type); if (!result) { Py_DECREF(attr_rec); return NULL; } result->db = db.release(); result->attr_rec = attr_rec; return result; } void register_db(PyObject* m) { common_init(); dpy_DB_Type.tp_new = PyType_GenericNew; if (PyType_Ready(&dpy_DB_Type) < 0) return; Py_INCREF(&dpy_DB_Type); PyModule_AddObject(m, "DB", (PyObject*)&dpy_DB_Type); } } } dballe-7.7/python/test-db.py0000755000175000017500000001754312652630043013006 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import dballe import os import io import datetime import unittest import warnings class DballeTest(unittest.TestCase): def setUp(self): if not hasattr(self, "assertCountEqual"): self.assertCountEqual = self.assertItemsEqual self.db = dballe.DB.connect_test() self.db.connect_test(); self.db.reset() data = dballe.Record( lat=12.34560, lon=76.54320, mobile=0, datetime=datetime.datetime(1945, 4, 25, 8, 0, 0), level=(10, 11, 15, 22), trange=(20,111,222), rep_memo="synop", B01011="Hey Hey!!", B01012=500) ids = self.db.insert_data(data, False, True) data.clear() data["B33007"] = 50 data["B33036"] = 75 self.db.attr_insert_data(ids["B01011"], data) for rec in self.db.query_data(dballe.Record(var="B01011")): self.attr_ref = rec["context_id"] def tearDown(self): self.db = None def testQueryAna(self): query = dballe.Record() cur = self.db.query_stations(query) self.assertEqual(cur.remaining, 1) count = 0 for result in cur: self.assertEqual(result["lat"], 12.34560) self.assertEqual(result["lon"], 76.54320) self.assertNotIn("B01011", result) count = count + 1 self.assertEqual(count, 1) def testQueryData(self): expected = {} expected["B01011"] = "Hey Hey!!"; expected["B01012"] = 500; query = dballe.Record() query["latmin"] = 10.0 cur = self.db.query_data(query) self.assertEqual(cur.remaining, 2) count = 0 for result in cur: self.assertEqual(cur.remaining, 2-count-1) var = result.var(result["var"]) assert var.code in expected self.assertEqual(var.enq(), expected[var.code]) del expected[var.code] count += 1 def testQueryAttrs(self): data = self.db.attr_query_data(self.attr_ref) self.assertCountEqual(data.keys(), ["B33007", "B33036"]) expected = {} expected["B33007"] = 50 expected["B33036"] = 75 count = 0 for code in data: self.assertIn(code, expected) self.assertEqual(data[code], expected[code]) del expected[code] count += 1 self.assertEqual(count, 2) def testQueryCursorAttrs(self): # Query a variable query = dballe.Record(var="B01011") cur = self.db.query_data(query); data = next(cur) self.assertTrue(data) attrs = cur.attr_query() expected = {} expected["B33007"] = 50 expected["B33036"] = 75 count = 0 for code in attrs: var = attrs.var(code) assert var.code in expected self.assertEqual(var.enq(), expected[var.code]) del expected[var.code] count = count + 1 self.assertEqual(count, 2) def testQuerySummary(self): query = dballe.Record() query["query"] = "details" cur = self.db.query_summary(query) res = dict() for result in cur: with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) res[(result["ana_id"], result["rep_memo"], result["level"], result["trange"], result["var"])] = ( result["datemin"], result["datemax"], result["context_id"]) self.assertEqual(res[(1, "synop", (10, 11, 15, 22), (20, 111, 222), 'B01011')], (datetime.datetime(1945, 4, 25, 8, 0), datetime.datetime(1945, 4, 25, 8, 0), 1)) self.assertEqual(res[(1, "synop", (10, 11, 15, 22), (20, 111, 222), 'B01012')], (datetime.datetime(1945, 4, 25, 8, 0), datetime.datetime(1945, 4, 25, 8, 0), 1)) def testQueryExport(self): query = dballe.Record() self.db.export_to_file(query, "BUFR", "/dev/null") self.db.export_to_file(query, "CREX", "/dev/null") self.db.export_to_file(query, "BUFR", "/dev/null", generic=True) self.db.export_to_file(query, "CREX", "/dev/null", generic=True) def testAttrRemove(self): #db.attrRemove(1, "B01011", [ "B33007" ]) self.db.attr_remove_data(self.attr_ref, ("B33007",)) def testLoadFile(self): with io.open(os.getenv("DBA_TESTDATA") + "/bufr/vad.bufr", "rb") as fp: self.db.reset() self.db.load(fp) self.assertTrue(self.db.query_data(dballe.Record()).remaining > 0) def testLoadFileLike(self): with io.open(os.getenv("DBA_TESTDATA") + "/bufr/vad.bufr", "rb") as fp: s = io.BytesIO(fp.read()) self.db.reset() self.db.load(s) self.assertTrue(self.db.query_data(dballe.Record()).remaining > 0) def testLoadFileno(self): import os class F(): def __init__(self, path): self.path = path def read(*args): raise AttributeError() def fileno(self): return self.fp.fileno() def __enter__(self): self.fp = open(self.path, "r") return self def __exit__(self, type, value, traceback): self.fp.close() with F(os.getenv("DBA_TESTDATA") + "/bufr/vad.bufr") as f: self.db.reset() self.db.load(f) self.assertTrue(self.db.query_data(dballe.Record()).remaining > 0) def testLoadAutodetect(self): # BUFR, autodetectable with io.open(os.getenv("DBA_TESTDATA") + "/bufr/vad.bufr", "rb") as fp: self.db.reset() self.assertEqual(self.db.load(fp), 25) # BUFR, not autodetectable with io.open(os.getenv("DBA_TESTDATA") + "/bufr/synop-groundtemp.bufr", "rb") as fp: self.db.reset() with self.assertRaises(KeyError): self.db.load(fp) # CREX, autodetectable with io.open(os.getenv("DBA_TESTDATA") + "/crex/test-synop0.crex", "rb") as fp: self.db.reset() self.assertEqual(self.db.load(fp), 1) # BUFR with io.open(os.getenv("DBA_TESTDATA") + "/bufr/vad.bufr", "rb") as fp: self.db.reset() self.assertEqual(self.db.load(fp, "BUFR"), 25) # BUFR with io.open(os.getenv("DBA_TESTDATA") + "/bufr/synop-groundtemp.bufr", "rb") as fp: self.db.reset() self.assertEqual(self.db.load(fp, "BUFR"), 1) # CREX loaded as BUFR yields no results with io.open(os.getenv("DBA_TESTDATA") + "/crex/test-synop0.crex", "rb") as fp: self.db.reset() self.assertEqual(self.db.load(fp, "BUFR"), 0) # CREX with io.open(os.getenv("DBA_TESTDATA") + "/crex/test-synop0.crex", "rb") as fp: self.db.reset() self.assertEqual(self.db.load(fp, "CREX"), 1) # BUFR loaded as CREX yields no results with io.open(os.getenv("DBA_TESTDATA") + "/bufr/vad.bufr", "rb") as fp: self.db.reset() self.assertEqual(self.db.load(fp, "CREX"), 0) def testQueryVolnd(self): from testlib import fill_volnd self.db.reset() fill_volnd(self.db) query = dballe.Record() query["var"] = "B10004" query["datetime"] = datetime.datetime(2007, 1, 1, 0, 0, 0) reports = [] for cur in self.db.query_data(query): reports.append(cur["rep_memo"]) s = "synop" t = "temp" self.assertEqual(reports, [s, t, s, t, s, t, s, s, t, s, t]) if __name__ == "__main__": from testlib import main main("test_db") dballe-7.7/python/dballe.cc0000644000175000017500000001256712652630043012622 00000000000000#include #include #include "common.h" #include "record.h" #include "db.h" #include "cursor.h" #include "dballe/types.h" #include "dballe/var.h" #include "config.h" #if PY_MAJOR_VERSION >= 3 #define PyInt_FromLong PyLong_FromLong #define PyInt_AsLong PyLong_AsLong #define PyInt_Check PyLong_Check #define Py_TPFLAGS_HAVE_ITER 0 #endif using namespace std; using namespace dballe; using namespace dballe::python; using namespace wreport; extern "C" { static PyObject* dballe_varinfo(PyTypeObject *type, PyObject *args, PyObject *kw) { const char* var_name; if (!PyArg_ParseTuple(args, "s", &var_name)) return NULL; return (PyObject*)wrpy->varinfo_create(dballe::varinfo(varcode_parse(var_name))); } static PyObject* dballe_var_uncaught(PyTypeObject *type, PyObject *args) { const char* var_name; PyObject* val = 0; if (!PyArg_ParseTuple(args, "s|O", &var_name, &val)) return NULL; if (val) { if (PyFloat_Check(val)) { double v = PyFloat_AsDouble(val); if (v == -1.0 && PyErr_Occurred()) return NULL; return (PyObject*)wrpy->var_create_d(dballe::varinfo(resolve_varcode(var_name)), v); } else if (PyInt_Check(val)) { long v = PyInt_AsLong(val); if (v == -1 && PyErr_Occurred()) return NULL; return (PyObject*)wrpy->var_create_i(dballe::varinfo(resolve_varcode(var_name)), (int)v); } else if ( PyUnicode_Check(val) #if PY_MAJOR_VERSION >= 3 || PyBytes_Check(val) #else || PyString_Check(val) #endif ) { string v; if (string_from_python(val, v)) return NULL; return (PyObject*)wrpy->var_create_c(dballe::varinfo(resolve_varcode(var_name)), v.c_str()); } else if (val == Py_None) { return (PyObject*)wrpy->var_create(dballe::varinfo(resolve_varcode(var_name))); } else { PyErr_SetString(PyExc_TypeError, "Expected int, float, str, unicode, or None"); return NULL; } } else return (PyObject*)wrpy->var_create(dballe::varinfo(resolve_varcode(var_name))); } static PyObject* dballe_var(PyTypeObject *type, PyObject *args) { try { return dballe_var_uncaught(type, args); } catch (wreport::error& e) { return raise_wreport_exception(e); } catch (std::exception& se) { return raise_std_exception(se); } } #define get_int_or_missing(intvar, ovar) \ int intvar; \ if (ovar == Py_None) \ intvar = MISSING_INT; \ else { \ intvar = PyInt_AsLong(ovar); \ if (intvar == -1 && PyErr_Occurred()) \ return NULL; \ } static PyObject* dballe_describe_level(PyTypeObject *type, PyObject *args, PyObject* kw) { static char* kwlist[] = { "ltype1", "l1", "ltype2", "l2", NULL }; PyObject* oltype1 = Py_None; PyObject* ol1 = Py_None; PyObject* oltype2 = Py_None; PyObject* ol2 = Py_None; if (!PyArg_ParseTupleAndKeywords(args, kw, "O|OOO", kwlist, &oltype1, &ol1, &oltype2, &ol2)) return NULL; get_int_or_missing(ltype1, oltype1); get_int_or_missing(l1, ol1); get_int_or_missing(ltype2, oltype2); get_int_or_missing(l2, ol2); Level lev(ltype1, l1, ltype2, l2); string desc = lev.describe(); return PyUnicode_FromString(desc.c_str()); } static PyObject* dballe_describe_trange(PyTypeObject *type, PyObject *args, PyObject* kw) { static char* kwlist[] = { "pind", "p1", "p2", NULL }; PyObject* opind = Py_None; PyObject* op1 = Py_None; PyObject* op2 = Py_None; if (!PyArg_ParseTupleAndKeywords(args, kw, "O|OO", kwlist, &opind, &op1, &op2)) return NULL; get_int_or_missing(pind, opind); get_int_or_missing(p1, op1); get_int_or_missing(p2, op2); Trange tr(pind, p1, p2); string desc = tr.describe(); return PyUnicode_FromString(desc.c_str()); } static PyMethodDef dballe_methods[] = { {"varinfo", (PyCFunction)dballe_varinfo, METH_VARARGS, "Query the DB-All.e variable table returning a Varinfo" }, {"var", (PyCFunction)dballe_var, METH_VARARGS, "Query the DB-All.e variable table returning a Var, optionally initialized with a value" }, {"describe_level", (PyCFunction)dballe_describe_level, METH_VARARGS | METH_KEYWORDS, "Return a string description for a level" }, {"describe_trange", (PyCFunction)dballe_describe_trange, METH_VARARGS | METH_KEYWORDS, "Return a string description for a time range" }, { NULL } }; #if PY_MAJOR_VERSION >= 3 static PyModuleDef dballe_module = { PyModuleDef_HEAD_INIT, "_dballe", /* m_name */ "DB-All.e Python interface.", /* m_doc */ -1, /* m_size */ dballe_methods, /* m_methods */ NULL, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ }; #endif #if PY_MAJOR_VERSION >= 3 PyMODINIT_FUNC PyInit__dballe(void) #else PyMODINIT_FUNC init_dballe(void) #endif { using namespace dballe::python; PyObject* m; #if PY_MAJOR_VERSION >= 3 m = PyModule_Create(&dballe_module); #else m = Py_InitModule3("_dballe", dballe_methods, "DB-All.e Python interface."); #endif register_record(m); register_db(m); register_cursor(m); #if PY_MAJOR_VERSION >= 3 return m; #endif } } dballe-7.7/python/Makefile.am0000644000175000017500000000271712652630271013123 00000000000000## Process this file with automake to produce Makefile.in TESTS_ENVIRONMENT = $(top_srcdir)/extra/runtest export PYTHONPATH=. dballe_python_tests = test-core.py test-record.py test-db.py test-volnd.py test-rconvert.py test-csv.py # TESTS = $(dballe_python_tests) pkgpython_PYTHON = dballe/dbacsv.py dballe/rconvert.py dballe/__init__.py dballe/volnd.py pyexec_LTLIBRARIES = _dballe.la _dballe_la_SOURCES = \ common.cc \ record.cc \ dballe.cc \ db.cc \ cursor.cc _dballe_la_CPPFLAGS = $(PYTHON_CFLAGS) _dballe_la_LDFLAGS = -module -avoid-version -export-symbols-regex init_dballe _dballe_la_LIBADD = ../dballe/libdballe.la doc_DATA = python-dballe.rst if HAVE_RST2HTML doc_DATA += python-dballe.html endif _dballe.so: _dballe.la ln -fs .libs/_dballe.so $@ python-dballe.rst: doc-dballe $(pkgpython_PYTHON) _dballe.so $(PYTHON) $(srcdir)/doc-dballe > $@ || (rm -f $@; false) python-dballe.html: python-dballe.rst rst2html $< > $@ || (rm -f $@; false) clean-local: rm -f *.pyc dballe/*.pyc _dballe.so rm -rf __pycache__ dballe/__pycache__ EXTRA_DIST = \ doc-dballe \ common.h \ record.h \ db.h \ cursor.h \ testlib.py \ MANIFEST.in \ setup.py \ $(dballe_python_tests) AM_CPPFLAGS = -I/usr/include/python$(PYTHON_VERSION) -I$(top_srcdir) check-local: _dballe.so for test in $(dballe_python_tests); do \ PYTHON="$(PYTHON)" $(TESTS_ENVIRONMENT) $$test ; \ done CLEANFILES = python-dballe.rst python-dballe.html dballe-7.7/python/test-record.py0000755000175000017500000003651712652630043013701 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import dballe import datetime import unittest import warnings class RecordTest(unittest.TestCase): def setUp(self): if not hasattr(self, "assertCountEqual"): self.assertCountEqual = self.assertItemsEqual self.r = dballe.Record( block=1, station=123, lat=45.12345, lon=11.54321, datetime=datetime.datetime(2007, 2, 1, 1, 2, 3), level=(105, 2), trange=(2, 3, 4), var="B12101", B12101=285.0) self.knownkeys = ["lat", "lon", "year", "month", "day", "hour", "min", "sec", "leveltype1", "l1", "leveltype2", "l2", "pindicator", "p1", "p2"] self.knownvars = ["B12101", "B01002", "B01001"] self.knownkeyvals = [45.12345, 11.54321, 2007, 2, 1, 1, 2, 3, 105, 2, 0, 0, 2, 3, 4] self.knownvarvals = [285.0, 123, 1] def testGet(self): self.assertEqual(self.r.get("block"), 1) self.assertEqual(self.r.get(key="block"), 1) self.assertEqual(self.r.get(key="ana_id", default="ciao"), "ciao") self.assertEqual(self.r.get("ana_id", default="ciao"), "ciao") with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) # date, datemin, datemax, now, when queried, are treated like a single # range. Querying them will likely be deprecated soon. self.assertEqual(self.r.get("datemin", None), datetime.datetime(2007, 2, 1, 1, 2, 3)) self.assertEqual(self.r.get("datemax", None), datetime.datetime(2007, 2, 1, 1, 2, 3)) def testVar(self): with self.assertRaises(TypeError): self.r.var() self.assertEqual(self.r.var("B12101").code, "B12101") def testKey(self): self.assertEqual(self.r.key("lon").code, "B00000") self.assertEqual(self.r.key("lon").enqd(), 11.54321) self.assertEqual(self.r.key("lon").enqi(), 1154321) self.assertEqual(self.r.key("lon").enqc(), "1154321") self.assertEqual(self.r.key("lon").enq(), 11.54321) self.assertEqual(self.r.get("lon"), self.r.key("lon").enqd()) def testMulti(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(self.r["date"], datetime.datetime(2007, 2, 1, 1, 2, 3)) self.assertEqual(self.r["level"], (105, 2, None, None)) self.assertEqual(self.r["timerange"], (2, 3, 4)) self.assertEqual(self.r["trange"], (2, 3, 4)) def testAlias(self): r = self.r.copy() r["t"] = 283.2 self.assertEqual(r["B12101"], 283.2) self.assertEqual(r["t"], 283.2) def testReadDictOperators(self): r = self.r self.assertEqual(r["block"], 1) self.assertEqual(r["station"], 123) self.assertEqual(r["lat"], 45.12345) self.assertEqual(r["lon"], 11.54321) self.assertEqual(r["B12101"], 285.0) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(r["date"], datetime.datetime(2007, 2, 1, 1, 2, 3)) self.assertEqual(r["level"], (105, 2, None, None)) self.assertEqual(r["timerange"], (2, 3, 4)) def testWriteDictOperators(self): r = self.r.copy() r["block"] = 2 r["station"] = 321 r["lat"] = 45.54321 r["lon"] = 11.12345 r["datetime"] = datetime.datetime(2006, 1, 2, 0, 1, 2) r["level"] = (104, 1, 105, 2) r["trange"] = (1, 2, 3) r["B12101"] = 294.5 self.assertEqual(r["block"], 2) self.assertEqual(r["station"], 321) self.assertEqual(r["lat"], 45.54321) self.assertEqual(r["lon"], 11.12345) self.assertEqual(r["B12101"], 294.5) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(r["date"], datetime.datetime(2006, 1, 2, 0, 1, 2)) self.assertEqual(r["level"], (104, 1, 105, 2)) self.assertEqual(r["timerange"], (1, 2, 3)) def testSpecials(self): r = self.r.copy() r["datetime"] = (datetime.datetime(2005, 3, 4, 5, 6, 7), datetime.datetime(2004, 4, 5, 6, 7, 8)) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) with self.assertRaises(KeyError): r["datetime"] self.assertEqual(r["datemin"], datetime.datetime(2005, 3, 4, 5, 6, 7)) self.assertEqual(r["datemax"], datetime.datetime(2004, 4, 5, 6, 7, 8)) self.assertEqual(r["level"], (105, 2, None, None)) self.assertEqual(r["timerange"], (2, 3, 4)) self.assertNotIn("date", r) self.assertIn("datemin", r) self.assertIn("datemax", r) self.assertIn("level", r) self.assertIn("timerange", r) del(r["datetime"]) del(r["level"]) del(r["trange"]) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(r.get("date", None), None) self.assertEqual(r.get("datemin", None), None) self.assertEqual(r.get("datemax", None), None) self.assertEqual(r.get("level", None), None) self.assertEqual(r.get("timerange", None), None) self.assertEqual("date" not in r, True) self.assertEqual("datemin" not in r, True) self.assertEqual("datemax" not in r, True) self.assertEqual("level" not in r, True) self.assertEqual("timerange" not in r, True) def testKeys(self): res = self.r.keys(); self.assertCountEqual(res, [ "lat", "lon", "year", "month", "day", "hour", "min", "sec", "leveltype1", "l1", "pindicator", "p1", "p2", "var", "B12101", "B01002", "B01001"]) def testVars(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) r = dballe.Record() self.assertEqual(r.vars(), ()) r["B33036"] = 75 self.assertEqual(r.vars(), (dballe.var("B33036", 75),)) res = self.r.vars() self.assertEqual(len(res), len(self.knownvars)) self.assertEqual(sorted(x.enq() for x in res), sorted(self.knownvarvals)) def testIter(self): r = dballe.Record() r["B33036"] = 75 r["B12101"] = 273.15 res = [] ri = iter(r) res.append(next(ri)) res.append(next(ri)) self.assertEqual(res, ["B12101", "B33036"]) def testSetDict(self): r = dballe.Record() r.update(ana_id=1, lat=12.34567, ident="ciao") self.assertEqual(r["ana_id"], 1) self.assertEqual(r["ident"], "ciao") self.assertEqual(r["lat"], 12.34567) self.assertEqual(len(r.keys()), 3) r.update(t=290.0) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(r.vars(), (dballe.var("B12101", 290.0),)) def testSetFromString(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) r = dballe.Record() r.set_from_string("ana_id=1") r.set_from_string("lat=12.34567") r.set_from_string("ident=ciao") r.set_from_string("B12101=32.5") r.set_from_string("l1=-") self.assertEqual(r["ana_id"], 1) self.assertEqual(r["ident"], "ciao") self.assertEqual(r["lat"], 12.34567) self.assertEqual(r["B12101"], 32.5) self.assertEqual(r["l1"], None) def testRecord(self): # Check basic set/get and variable iteration rec = dballe.Record() self.assertEqual("ana_id" in rec, False) rec["ana_id"] = 3 self.assertEqual("ana_id" in rec, True) self.assertEqual(rec["ana_id"], 3) self.assertEqual("B04001" in rec, False) rec["B04001"] = 2001 self.assertEqual("B04001" in rec, True) self.assertEqual(rec["B04001"], 2001) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) count = 0 for var in rec.vars(): self.assertEqual(var.code, "B04001") count += 1 self.assertEqual(count, 1) del rec["block"] self.assertEqual("block" in rec, False) del rec["B04001"] self.assertEqual("B04001" in rec, False) d = datetime.datetime(2001, 2, 3, 4, 5, 6) rec["datetime"] = d self.assertEqual(rec["year"], 2001) self.assertEqual(rec["month"], 2) self.assertEqual(rec["day"], 3) self.assertEqual(rec["hour"], 4) self.assertEqual(rec["min"], 5) self.assertEqual(rec["sec"], 6) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(rec["date"], d) self.assertEqual(rec["datetime"], d) l = (1, 2, 1, 3) rec["level"] = l self.assertEqual(rec["leveltype1"], 1) self.assertEqual(rec["l1"], 2) self.assertEqual(rec["leveltype2"], 1) self.assertEqual(rec["l2"], 3) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(rec["level"], l) t = (4, 5, 6) rec["trange"] = t self.assertEqual(rec["pindicator"], 4) self.assertEqual(rec["p1"], 5) self.assertEqual(rec["p2"], 6) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(rec["timerange"], t) self.assertEqual(rec["trange"], t) # Test that KeyError is raised for several different types of lookup rec = dballe.Record() self.assertRaises(KeyError, rec.__getitem__, "year") self.assertRaises(KeyError, rec.__getitem__, "B01001") with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertRaises(KeyError, rec.__getitem__, "date") self.assertRaises(KeyError, rec.__getitem__, "level") self.assertRaises(KeyError, rec.__getitem__, "trange") self.assertRaises(KeyError, rec.__getitem__, "timerange") rec["datetime"] = None with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(rec.get("date", None), None) def testRecordClear(self): rec = dballe.Record(ana_id=1, B12101=21.5) self.assertIn("ana_id", rec); self.assertIn("B12101", rec); rec.clear() self.assertNotIn("ana_id", rec); self.assertNotIn("B12101", rec); rec.update(ana_id=1, B12101=21.5) self.assertIn("ana_id", rec); self.assertIn("B12101", rec); rec.clear_vars() self.assertIn("ana_id", rec); self.assertNotIn("B12101", rec); def testRecordConstructor(self): rec = dballe.Record( ana_id=1, datetime=datetime.datetime(2001, 2, 3, 4, 5, 6) ) self.assertEqual(rec["ana_id"], 1) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(rec["date"], datetime.datetime(2001, 2, 3, 4, 5, 6)) def testRecordCopying(self): # Try out all copying functions master = dballe.Record() master["block"] = 4 master["latmin"] = 4.1234 master["B01001"] = 4 if True: r1 = master; self.assertEqual(r1["block"], 4) self.assertEqual(r1["latmin"], 4.1234) self.assertEqual(r1["B01001"], 4) r2 = master.copy() self.assertEqual(r2["block"], 4) self.assertEqual(r2["latmin"], 4.1234) self.assertEqual(r2["B01001"], 4) r3 = r2.copy() self.assertEqual(r3["block"], 4) self.assertEqual(r3["latmin"], 4.1234) self.assertEqual(r3["B01001"], 4) del r2["latmin"] self.assertEqual(r3["latmin"], 4.1234) r3["latmin"] = 4.3214 self.assertEqual(r3["latmin"], 4.3214) r3 = r3 self.assertEqual(r3["block"], 4) self.assertEqual(r3["latmin"], 4.3214) self.assertEqual(r3["B01001"], 4) master = r3 self.assertEqual(master["block"], 4) self.assertEqual(master["latmin"], 4.3214) self.assertEqual(master["B01001"], 4) def testRecordCopying1(self): # This caused a repeatable segfault rec = dballe.Record() rec["query"] = "nosort" rec1 = rec.copy() rec1["query"] = "nosort" def testParseDateExtremes(self): # Test the parse_date_extremes implementation with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) rec = dballe.Record() a, b = rec.date_extremes() self.assertEqual(a, None) self.assertEqual(b, None) rec["yearmin"] = 2000 a, b = rec.date_extremes() self.assertEqual(a, datetime.datetime(2000, 1, 1, 0, 0, 0)) self.assertEqual(b, None) rec["yearmin"] = None rec["yearmax"] = 1900 rec["monthmax"] = 2 a, b = rec.date_extremes() self.assertEqual(a, None) self.assertEqual(b, datetime.datetime(1900, 2, 28, 23, 59, 59)) rec["yearmax"] = 2000 rec["monthmax"] = 2 a, b = rec.date_extremes() self.assertEqual(a, None) self.assertEqual(b, datetime.datetime(2000, 2, 29, 23, 59, 59)) rec["yearmax"] = 2001 rec["monthmax"] = 2 a, b = rec.date_extremes() self.assertEqual(a, None) self.assertEqual(b, datetime.datetime(2001, 2, 28, 23, 59, 59)) rec["yearmax"] = 2004 rec["monthmax"] = 2 a, b = rec.date_extremes() self.assertEqual(a, None) self.assertEqual(b, datetime.datetime(2004, 2, 29, 23, 59, 59)) def testCompare(self): a = dballe.Record(ana_id=1, ident="ciao", B12101=23.1) b = dballe.Record(ana_id=1, ident="ciao", B12101=23.1) self.assertTrue(a == b) self.assertFalse(a != b) a["ana_id"] = 2 self.assertTrue(a != b) self.assertFalse(a == b) def testSetTuplesToNone(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) a = dballe.Record(level=(1, 2, 3, 4), trange=(1, 2, 3)) self.assertEqual(a["level"], (1, 2, 3, 4)) self.assertEqual(a["trange"], (1, 2, 3)) a["level"] = None with self.assertRaises(KeyError): a["level"] self.assertEqual(a["trange"], (1, 2, 3)) a["trange"] = None with self.assertRaises(KeyError): a["level"] with self.assertRaises(KeyError): a["trange"] if __name__ == "__main__": from testlib import main main("test_record") dballe-7.7/python/common.cc0000644000175000017500000002727612652630043012672 00000000000000#include "common.h" #include #include #include "config.h" #if PY_MAJOR_VERSION >= 3 #define PyInt_FromLong PyLong_FromLong #define PyInt_AsLong PyLong_AsLong #define PyInt_Type PyLong_Type #endif using namespace wreport; namespace dballe { namespace python { wrpy_c_api* wrpy = 0; PyObject* format_varcode(wreport::Varcode code) { char buf[7]; snprintf(buf, 7, "%c%02d%03d", WR_VAR_F(code) == 0 ? 'B' : WR_VAR_F(code) == 1 ? 'R' : WR_VAR_F(code) == 2 ? 'C' : WR_VAR_F(code) == 3 ? 'D' : '?', WR_VAR_X(code), WR_VAR_Y(code)); return PyUnicode_FromString(buf); } void set_wreport_exception(const wreport::error& e) { switch (e.code()) { case WR_ERR_NONE: PyErr_SetString(PyExc_SystemError, e.what()); break; case WR_ERR_NOTFOUND: // Item not found PyErr_SetString(PyExc_KeyError, e.what()); break; case WR_ERR_TYPE: // Wrong variable type PyErr_SetString(PyExc_TypeError, e.what()); break; case WR_ERR_ALLOC: // Cannot allocate memory PyErr_SetString(PyExc_MemoryError, e.what()); break; case WR_ERR_ODBC: // ODBC error PyErr_SetString(PyExc_OSError, e.what()); break; case WR_ERR_HANDLES: // Handle management error PyErr_SetString(PyExc_SystemError, e.what()); break; case WR_ERR_TOOLONG: // Buffer is too short to fit data PyErr_SetString(PyExc_ValueError, e.what()); break; case WR_ERR_SYSTEM: // Error reported by the system PyErr_SetString(PyExc_OSError, e.what()); break; case WR_ERR_CONSISTENCY: // Consistency check failed PyErr_SetString(PyExc_RuntimeError, e.what()); break; case WR_ERR_PARSE: // Parse error PyErr_SetString(PyExc_ValueError, e.what()); break; case WR_ERR_WRITE: // Write error PyErr_SetString(PyExc_RuntimeError, e.what()); break; case WR_ERR_REGEX: // Regular expression error PyErr_SetString(PyExc_ValueError, e.what()); break; case WR_ERR_UNIMPLEMENTED: // Feature not implemented PyErr_SetString(PyExc_NotImplementedError, e.what()); break; case WR_ERR_DOMAIN: // Value outside acceptable domain PyErr_SetString(PyExc_OverflowError, e.what()); break; default: PyErr_Format(PyExc_SystemError, "unhandled exception with code %d: %s", e.code(), e.what()); break; } } PyObject* raise_wreport_exception(const wreport::error& e) { set_wreport_exception(e); return nullptr; } void set_std_exception(const std::exception& e) { PyErr_SetString(PyExc_RuntimeError, e.what()); } PyObject* raise_std_exception(const std::exception& e) { set_std_exception(e); return NULL; } PyObject* datetime_to_python(const Datetime& dt) { if (dt.is_missing()) { Py_INCREF(Py_None); return Py_None; } return PyDateTime_FromDateAndTime( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, 0); } int datetime_from_python(PyObject* dt, Datetime& out) { if (dt == NULL || dt == Py_None) { out = Datetime(); return 0; } if (!PyDateTime_Check(dt)) { PyErr_SetString(PyExc_TypeError, "value must be an instance of datetime.datetime"); return -1; } out = Datetime( PyDateTime_GET_YEAR((PyDateTime_DateTime*)dt), PyDateTime_GET_MONTH((PyDateTime_DateTime*)dt), PyDateTime_GET_DAY((PyDateTime_DateTime*)dt), PyDateTime_DATE_GET_HOUR((PyDateTime_DateTime*)dt), PyDateTime_DATE_GET_MINUTE((PyDateTime_DateTime*)dt), PyDateTime_DATE_GET_SECOND((PyDateTime_DateTime*)dt)); return 0; } int datetimerange_from_python(PyObject* val, DatetimeRange& out) { if (PySequence_Size(val) != 2) { PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of datetime() objects"); return -1; } pyo_unique_ptr dtmin(PySequence_GetItem(val, 0)); pyo_unique_ptr dtmax(PySequence_GetItem(val, 1)); if (datetime_from_python(dtmin, out.min)) return -1; if (datetime_from_python(dtmax, out.max)) return -1; return 0; } namespace { /// Convert an integer to Python, returning None if it is MISSING_INT PyObject* dballe_int_to_python(int val) { if (val == MISSING_INT) { Py_INCREF(Py_None); return Py_None; } else return PyInt_FromLong(val); } /// Convert a Python object to an integer, returning MISSING_INT if it is None int dballe_int_from_python(PyObject* o, int& out) { if (o == NULL || o == Py_None) { out = MISSING_INT; return 0; } int res = PyInt_AsLong(o); if (res == -1 && PyErr_Occurred()) return -1; out = res; return 0; } } PyObject* level_to_python(const Level& lev) { if (lev.is_missing()) { Py_INCREF(Py_None); return Py_None; } PyObject* res = PyTuple_New(4); if (!res) return NULL; if (PyObject* v = dballe_int_to_python(lev.ltype1)) PyTuple_SET_ITEM(res, 0, v); else { Py_DECREF(res); return NULL; } if (PyObject* v = dballe_int_to_python(lev.l1)) PyTuple_SET_ITEM(res, 1, v); else { Py_DECREF(res); return NULL; } if (PyObject* v = dballe_int_to_python(lev.ltype2)) PyTuple_SET_ITEM(res, 2, v); else { Py_DECREF(res); return NULL; } if (PyObject* v = dballe_int_to_python(lev.l2)) PyTuple_SET_ITEM(res, 3, v); else { Py_DECREF(res); return NULL; } return res; } int level_from_python(PyObject* o, Level& out) { if (o == NULL || o == Py_None) { out = Level(); return 0; } if (!PyTuple_Check(o)) { PyErr_SetString(PyExc_TypeError, "level must be a tuple"); return -1; } unsigned size = PyTuple_Size(o); if (size > 4) { PyErr_SetString(PyExc_TypeError, "level tuple must have at most 4 elements"); return -1; } Level res; if (size < 1) { out = res; return 0; } if (int err = dballe_int_from_python(PyTuple_GET_ITEM(o, 0), res.ltype1)) return err; if (size < 2) { out = res; return 0; } if (int err = dballe_int_from_python(PyTuple_GET_ITEM(o, 1), res.l1)) return err; if (size < 3) { out = res; return 0; } if (int err = dballe_int_from_python(PyTuple_GET_ITEM(o, 2), res.ltype2)) return err; if (size < 4) { out = res; return 0; } if (int err = dballe_int_from_python(PyTuple_GET_ITEM(o, 3), res.l2)) return err; out = res; return 0; } PyObject* trange_to_python(const Trange& tr) { if (tr.is_missing()) { Py_INCREF(Py_None); return Py_None; } PyObject* res = PyTuple_New(3); if (!res) return NULL; if (PyObject* v = dballe_int_to_python(tr.pind)) PyTuple_SET_ITEM(res, 0, v); else { Py_DECREF(res); return NULL; } if (PyObject* v = dballe_int_to_python(tr.p1)) PyTuple_SET_ITEM(res, 1, v); else { Py_DECREF(res); return NULL; } if (PyObject* v = dballe_int_to_python(tr.p2)) PyTuple_SET_ITEM(res, 2, v); else { Py_DECREF(res); return NULL; } return res; } int trange_from_python(PyObject* o, Trange& out) { if (o == NULL || o == Py_None) { out = Trange(); return 0; } if (!PyTuple_Check(o)) { PyErr_SetString(PyExc_TypeError, "time range must be a tuple"); return -1; } unsigned size = PyTuple_Size(o); if (size > 3) { PyErr_SetString(PyExc_TypeError, "time range tuple must have at most 3 elements"); return -1; } Trange res; if (size < 1) { out = res; return 0; } if (int err = dballe_int_from_python(PyTuple_GET_ITEM(o, 0), res.pind)) return err; if (size < 2) { out = res; return 0; } if (int err = dballe_int_from_python(PyTuple_GET_ITEM(o, 1), res.p1)) return err; if (size < 3) { out = res; return 0; } if (int err = dballe_int_from_python(PyTuple_GET_ITEM(o, 2), res.p2)) return err; out = res; return 0; } int string_from_python(PyObject* o, std::string& out) { #if PY_MAJOR_VERSION >= 3 if (PyBytes_Check(o)) { const char* v = PyBytes_AsString(o); if (v == NULL) return -1; out = v; return 0; } #else if (PyString_Check(o)) { const char* v = PyString_AsString(o); if (v == NULL) return -1; out = v; return 0; } #endif if (PyUnicode_Check(o)) { #if PY_MAJOR_VERSION >= 3 const char* v = PyUnicode_AsUTF8(o); if (v == NULL) return -1; out = v; return 0; #else PyObject *utf8 = PyUnicode_AsUTF8String(o); const char* v = PyString_AsString(utf8); if (v == NULL) { Py_DECREF(utf8); return -1; } out = v; Py_DECREF(utf8); return 0; #endif } PyErr_SetString(PyExc_TypeError, "value must be an instance of str, bytes or unicode"); return -1; } int file_get_fileno(PyObject* o) { // fileno_value = obj.fileno() pyo_unique_ptr fileno_meth(PyObject_GetAttrString(o, "fileno")); if (!fileno_meth) return -1; pyo_unique_ptr fileno_args(Py_BuildValue("()")); if (!fileno_args) return -1; PyObject* fileno_value = PyObject_Call(fileno_meth, fileno_args, NULL); if (!fileno_value) { if (PyErr_ExceptionMatches(PyExc_AttributeError) || PyErr_ExceptionMatches(PyExc_IOError)) PyErr_Clear(); return -1; } // fileno = int(fileno_value) if (!PyObject_TypeCheck(fileno_value, &PyInt_Type)) { PyErr_SetString(PyExc_ValueError, "fileno() function must return an integer"); return -1; } return PyInt_AsLong(fileno_value); } PyObject* file_get_data(PyObject* o, char*&buf, Py_ssize_t& len) { // Use read() instead pyo_unique_ptr read_meth(PyObject_GetAttrString(o, "read")); pyo_unique_ptr read_args(Py_BuildValue("()")); pyo_unique_ptr data(PyObject_Call(read_meth, read_args, NULL)); if (!data) return nullptr; #if PY_MAJOR_VERSION >= 3 if (!PyObject_TypeCheck(data, &PyBytes_Type)) { PyErr_SetString(PyExc_ValueError, "read() function must return a bytes object"); return nullptr; } if (PyBytes_AsStringAndSize(data, &buf, &len)) return nullptr; #else if (!PyObject_TypeCheck(data, &PyString_Type)) { Py_DECREF(data); PyErr_SetString(PyExc_ValueError, "read() function must return a string object"); return nullptr; } if (PyString_AsStringAndSize(data, &buf, &len)) return nullptr; #endif return data.release(); } int object_repr(PyObject* o, std::string& out) { pyo_unique_ptr fileno_repr(PyObject_Repr(o)); if (!fileno_repr) return -1; std::string name; if (string_from_python(fileno_repr, name)) return -1; return 0; } int common_init() { /* * PyDateTimeAPI, that is used by all the PyDate* and PyTime* macros, is * defined as a static variable defaulting to NULL, and it needs to be * initialized on each and every C file where it is used. * * Therefore, we need to have a common_init() to call from all * initialization functions. *sigh* */ if (!PyDateTimeAPI) PyDateTime_IMPORT; if (!wrpy) { wrpy = (wrpy_c_api*)PyCapsule_Import("_wreport._C_API", 0); if (!wrpy) return -1; } return 0; } } } dballe-7.7/python/testlib.py0000644000175000017500000000713412652630043013102 00000000000000# coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import shlex import os import sys import unittest def main(testname): args = os.environ.get("ARGS", None) if args is None: return unittest.main() args = shlex.split(args); if args[0] != testname: return 0 argv = [sys.argv[0]] + args[1:] unittest.main(argv=argv) def not_so_random(seed): """ Predictable random number generator, independent from python versions """ # see https://en.wikipedia.org/wiki/Linear_congruential_generator m = 2**31 a = 1103515245 c = 12345 while True: seed = (a * seed + c) % m yield float(seed) / float(m) def fill_volnd(db): import dballe import datetime # We want a predictable dataset rdata = not_so_random(1) rattr = not_so_random(2) # Wipe the test database db.reset() attrs = dballe.Record() rec = dballe.Record(mobile=0) def contexts(): # 2 networks for net in ('synop', 'temp'): # 6 stations for lat in (10., 20., 30.): for lon in (15., 25.): yield net, lat, lon def dtrange(start, stop, delta): while (start < stop): yield start start += delta def everyxhours(x): return dtrange( datetime.datetime(2007, 1, 1, 0, 0, 0), datetime.datetime(2007, 1, 7, 0, 0, 0), datetime.timedelta(0, x * 3600, 0)) def maybe_insert(rec, aname): if next(rdata) > 0.9: return ids = db.insert_data(rec, False, True) attrs.clear() attrs[aname] = next(rattr) * 100. for code in rec: if not code.startswith("B"): continue db.attr_insert_data(ids[code], attrs) # Enter some sample data for net, lat, lon in contexts(): rec["rep_memo"] = net if net == 'synop': aname = 'B33007' else: aname = 'B33040' rec["lat"] = lat rec["lon"] = lon # 6 hours precipitations rec["level"] = (1,) rec["trange"] = (4, -21600, 0) for dt in everyxhours(6): rec["datetime"] = dt rec["B13011"] = next(rdata) * 10. maybe_insert(rec, aname) # 12 hours precipitations at different times rec["level"] = (1,) rec["trange"] = (4, -43200, 0) for dt in everyxhours(12): rec["datetime"] = dt rec["B13011"] = next(rdata) * 10. maybe_insert(rec, aname) # Randomly measured # precipitations on a different # (meaningless) level # At slightly off times rec["level"] = (3, 2) rec["trange"] = (4, -21600, 0) for dt in everyxhours(6): rec["datetime"] = (dt + datetime.timedelta(0, - 600 + int(next(rdata) * 1200))) rec["B13011"] = next(rdata) * 10. maybe_insert(rec, aname) del rec["B13011"] # Pressures every 12 hours rec["level"] = (1,) rec["trange"] = (0,) for dt in everyxhours(12): rec["datetime"] = dt rec["B10004"] = float(70000 + next(rdata) * 35000) maybe_insert(rec, aname) del rec["B10004"] # Insert some pseudoana data for the station 1, to test # pseudoana export and mixed data types rec.clear() rec.update(ana_id=1, B01001=12, B01002=123, B01019="Test of long station name", rep_memo="synop") db.insert_station_data(rec, False, True) dballe-7.7/python/record.h0000644000175000017500000000101512652630043012501 00000000000000#ifndef DBALLE_PYTHON_RECORD_H #define DBALLE_PYTHON_RECORD_H #include namespace dballe { struct Record; } extern "C" { typedef struct { PyObject_HEAD dballe::Record* rec; bool station_context; } dpy_Record; PyAPI_DATA(PyTypeObject) dpy_Record_Type; #define dpy_Record_Check(ob) \ (Py_TYPE(ob) == &dpy_Record_Type || \ PyType_IsSubtype(Py_TYPE(ob), &dpy_Record_Type)) } namespace dballe { namespace python { dpy_Record* record_create(); void register_record(PyObject* m); } } #endif dballe-7.7/python/cursor.cc0000644000175000017500000001660112652630043012705 00000000000000#include #include #include "cursor.h" #include "record.h" #include "db.h" #include "common.h" #include #include "config.h" #if PY_MAJOR_VERSION >= 3 #define PyInt_FromLong PyLong_FromLong #define PyInt_AsLong PyLong_AsLong #define PyInt_Check PyLong_Check #define PyInt_Type PyLong_Type #define Py_TPFLAGS_HAVE_ITER 0 #endif using namespace std; using namespace dballe; using namespace dballe::python; using namespace wreport; extern "C" { static PyObject* dpy_Cursor_remaining(dpy_Cursor* self, void* closure) { return PyInt_FromLong(self->cur->remaining()); } static PyGetSetDef dpy_Cursor_getsetters[] = { {"remaining", (getter)dpy_Cursor_remaining, NULL, "number of results still to be returned", NULL }, {NULL} }; static PyObject* dpy_Cursor_query_attrs(dpy_Cursor* self, PyObject* args, PyObject* kw) { if (PyErr_WarnEx(PyExc_DeprecationWarning, "please use Cursor.attr_query, DB.attr_query_station or DB.attr_query_data instead of Cursor.query_attrs", 1)) return NULL; static char* kwlist[] = { "attrs", NULL }; PyObject* attrs = 0; if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", kwlist, &attrs)) return NULL; // Read the attribute list, if provided db::AttrList codes; if (db_read_attrlist(attrs, codes)) return NULL; self->db->attr_rec->rec->clear(); try { if (auto c = dynamic_cast(self->cur)) c->get_db().attr_query_station(c->attr_reference_id(), [&](unique_ptr&& var) { if (!codes.empty() && find(codes.begin(), codes.end(), var->code()) == codes.end()) return; self->db->attr_rec->rec->set(move(var)); }); else if (auto c = dynamic_cast(self->cur)) c->get_db().attr_query_data(c->attr_reference_id(), [&](unique_ptr&& var) { if (!codes.empty() && find(codes.begin(), codes.end(), var->code()) == codes.end()) return; self->db->attr_rec->rec->set(move(var)); }); else { PyErr_SetString(PyExc_ValueError, "the cursor does ont come from DB.query_station_data or DB.query_data"); return NULL; } Py_INCREF(self->db->attr_rec); return (PyObject*)self->db->attr_rec; } DBALLE_CATCH_RETURN_PYO } static PyObject* dpy_Cursor_attr_query(dpy_Cursor* self) { self->db->attr_rec->rec->clear(); try { if (auto c = dynamic_cast(self->cur)) c->get_db().attr_query_station(c->attr_reference_id(), [&](unique_ptr&& var) { self->db->attr_rec->rec->set(move(var)); }); else if (auto c = dynamic_cast(self->cur)) c->get_db().attr_query_data(c->attr_reference_id(), [&](unique_ptr&& var) { self->db->attr_rec->rec->set(move(var)); }); else { PyErr_SetString(PyExc_ValueError, "the cursor does ont come from DB.query_station_data or DB.query_data"); return NULL; } Py_INCREF(self->db->attr_rec); return (PyObject*)self->db->attr_rec; } DBALLE_CATCH_RETURN_PYO } static PyMethodDef dpy_Cursor_methods[] = { {"query_attrs", (PyCFunction)dpy_Cursor_query_attrs, METH_VARARGS | METH_KEYWORDS, "Query attributes for the current variable" }, {"attr_query", (PyCFunction)dpy_Cursor_attr_query, METH_NOARGS, "Query attributes for the current variable" }, {NULL} }; static int dpy_Cursor_init(dpy_Cursor* self, PyObject* args, PyObject* kw) { // People should not invoke Cursor() as a constructor, but if they do, // this is better than a segfault later on PyErr_SetString(PyExc_NotImplementedError, "Cursor objects cannot be constructed explicitly"); return -1; } static void dpy_Cursor_dealloc(dpy_Cursor* self) { delete self->cur; Py_DECREF(self->rec); Py_DECREF(self->db); } static PyObject* dpy_Cursor_iter(dpy_Cursor* self) { Py_INCREF(self); return (PyObject*)self; } static PyObject* dpy_Cursor_iternext(dpy_Cursor* self) { if (self->cur->next()) { self->cur->to_record(*self->rec->rec); Py_INCREF(self->rec); return (PyObject*)self->rec; } else { PyErr_SetNone(PyExc_StopIteration); return NULL; } } static PyObject* dpy_Cursor_str(dpy_Cursor* self) { /* std::string f = self->var.format("None"); return PyUnicode_FromString(f.c_str()); */ return PyUnicode_FromString("Cursor"); } static PyObject* dpy_Cursor_repr(dpy_Cursor* self) { /* string res = "Var('"; res += varcode_format(self->var.code()); if (self->var.info()->is_string()) { res += "', '"; res += self->var.format(); res += "')"; } else { res += "', "; res += self->var.format("None"); res += ")"; } return PyUnicode_FromString(res.c_str()); */ return PyUnicode_FromString("Cursor object"); } PyTypeObject dpy_Cursor_Type = { PyVarObject_HEAD_INIT(NULL, 0) "dballe.Cursor", // tp_name sizeof(dpy_Cursor), // tp_basicsize 0, // tp_itemsize (destructor)dpy_Cursor_dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare (reprfunc)dpy_Cursor_repr, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping 0, // tp_hash 0, // tp_call (reprfunc)dpy_Cursor_str, // tp_str 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, // tp_flags "DB-All.e Cursor", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset (getiterfunc)dpy_Cursor_iter, // tp_iter (iternextfunc)dpy_Cursor_iternext, // tp_iternext dpy_Cursor_methods, // tp_methods 0, // tp_members dpy_Cursor_getsetters, // tp_getset 0, // tp_base 0, // tp_dict 0, // tp_descr_get 0, // tp_descr_set 0, // tp_dictoffset (initproc)dpy_Cursor_init, // tp_init 0, // tp_alloc 0, // tp_new }; } namespace dballe { namespace python { dpy_Cursor* cursor_create(dpy_DB* db, std::unique_ptr cur) { dpy_Cursor* result = PyObject_New(dpy_Cursor, &dpy_Cursor_Type); if (!result) return NULL; Py_INCREF(db); result->db = db; result->cur = cur.release(); result->rec = record_create(); return result; } void register_cursor(PyObject* m) { common_init(); dpy_Cursor_Type.tp_new = PyType_GenericNew; if (PyType_Ready(&dpy_Cursor_Type) < 0) return; Py_INCREF(&dpy_Cursor_Type); PyModule_AddObject(m, "Cursor", (PyObject*)&dpy_Cursor_Type); } } } dballe-7.7/python/test-csv.py0000755000175000017500000000457712652630043013217 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import dballe from dballe import dbacsv import datetime import unittest import io class TestCSV(unittest.TestCase): def setUp(self): from testlib import fill_volnd self.db = dballe.DB.connect_test() fill_volnd(self.db) def testExport(self): query = dballe.Record() #query["rep_memo"] = "synop" out = io.StringIO() dbacsv.export(self.db, query, out) lines = out.getvalue().splitlines() self.assertEqual(lines[0], "Station B01001: 12; Station B01002: 123; Station B01019: Test of long station name,,,,,,,,,,,,,,,") self.assertEqual(lines[1], "Station,Latitude,Longitude,Network,Datetime,Level1,L1,Level2,L2,Time range,P1,P2,Variable,Value,Attr B33007,Attr B33040") self.assertEqual(lines[2], "1,10.0,15.0,temp,2006-12-31 23:53:12,3,2,-,-,4,-21600,0,B13011,3.0,,17") def testAttrs(self): self.db.reset() data = dballe.Record() data.update( rep_memo="synop", lat=0.0, lon=0.0, ident="#000000", level=(103, 2000), trange=(254, 0, 0), datetime=datetime.datetime(1005, 1, 1, 1, 1, 0), B12101=270.96) ids = self.db.insert_data(data, False, True) attrs = dballe.Record() attrs["B33209"] = 98 self.db.attr_insert_data(ids["B12101"], attrs) data.update( rep_memo="synop", lat=0.0, lon=0.0, ident="#000000", level=(103, 2000), trange=(254, 0, 0), datetime=datetime.datetime(1005, 1, 1, 1, 1, 1), B12101=271.96) ids = self.db.insert_data(data, False, True) attrs = dballe.Record() attrs["B33209"] = 100 self.db.attr_insert_data(ids["B12101"], attrs) query = dballe.Record() out = io.StringIO() dbacsv.export(self.db, query, out) lines = out.getvalue().splitlines() self.assertEqual(lines[2], "1005-01-01 01:01:00,270.96,98") self.assertEqual(lines[3], "1005-01-01 01:01:01,271.96,100") if __name__ == "__main__": from testlib import main main("test_csv") dballe-7.7/python/dballe/0000755000175000017500000000000012653425053012364 500000000000000dballe-7.7/python/dballe/dbacsv.py0000644000175000017500000002665212652630043014127 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import dballe import csv import sys import warnings """ Export data from DB-All.e into CSV format """ def intormiss(x): """ Format an integer to a string, returning '-' if the integer is None. """ if x is None: return "-" else: return "%d" % x class UnicodeCSVWriter(object): """ Hack to work around the csv module being unable to handle unicode rows in input, and unicode files in output """ class UnicodeFdWrapper(object): """ Wrap an output file descriptor into something that accepts utf8 byte strings and forwards unicode """ def __init__(self, outfd): self.outfd = outfd def write(self, bytestr): self.outfd.write(bytestr.decode("utf-8")) def __init__(self, outfd, *writer_args, **writer_kw): self.writer = csv.writer(self.UnicodeFdWrapper(outfd), *writer_args, **writer_kw) def encode_field(self, val): encode = getattr(val, "encode", None) if encode is not None: return encode("utf-8") else: return val def writerow(self, row): enc = self.encode_field self.writer.writerow([enc(s) for s in row]) class Column(object): def __init__(self): self.values = set() def is_single_val(self): return len(self.values) == 1 def column_labels(self): return [self.LABEL] def title(self): return "{} {}".format(self.LABEL, next(iter(self.values))) class ColumnStation(Column): def __init__(self, stations): super(ColumnStation, self).__init__() self.stations = stations self.idents = set() def add(self, row): self.values.add(row["ana_id"]) ident = row.get("ident", None) if ident is not None: self.idents.add(ident) def title(self): id = next(iter(self.values)) lat, lon, ident = self.stations[id] if ident is None: return "Fixed station, lat {}, lon {}".format(lat, lon) else: return "Mobile station {}, lat {}, lon {}".format(ident, lat, lon) def column_labels(self): res = ["Station", "Latitude", "Longitude"] if self.idents: res.append("Ident") return res def column_data(self, rec): id = rec["ana_id"] lat, lon, ident = self.stations[id] res = [id, lat, lon] if self.idents: res.append(ident or "") return res class ColumnNetwork(Column): LABEL = "Network" def add(self, row): self.values.add(row["rep_memo"]) def column_data(self, rec): return [rec["rep_memo"]] class ColumnDatetime(Column): LABEL = "Datetime" def add(self, row): # Suppress deprecation warnings until we have something better with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.values.add(row["date"]) def title(self): return str(next(iter(self.values))) def column_data(self, rec): # Suppress deprecation warnings until we have something better with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) return [rec["date"]] class ColumnLevel(Column): def add(self, row): # Suppress deprecation warnings until we have something better with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.values.add(",".join([intormiss(x) for x in row["level"]])) def title(self): return "Level {}".format(next(iter(self.values))) def column_labels(self): return ["Level1", "L1", "Level2", "L2"] def column_data(self, rec): # Suppress deprecation warnings until we have something better with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) lev = rec["level"] return [ intormiss(lev[0]), intormiss(lev[1]), intormiss(lev[2]), intormiss(lev[3]) ] class ColumnTrange(Column): def add(self, row): # Suppress deprecation warnings until we have something better with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.values.add(",".join([intormiss(x) for x in row["trange"]])) def title(self): return "Time range {}".format(next(iter(self.values))) def column_labels(self): return ["Time range", "P1", "P2"] def column_data(self, rec): # Suppress deprecation warnings until we have something better with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) tr = rec["trange"] return [ intormiss(tr[0]), intormiss(tr[1]), intormiss(tr[2]) ] class ColumnVar(Column): LABEL = "Variable" def add(self, row): self.values.add(row["var"]) def column_data(self, rec): return [rec["var"]] class ColumnValue(Column): LABEL = "Value" def add(self, row): self.values.add(row.var(row["var"]).format("")) def column_data(self, rec): return [rec.var(rec["var"]).format("")] class ColumnStationData(Column): def __init__(self, varcode, station_data): super(ColumnStationData, self).__init__() self.varcode = varcode # { Station id: { varcode: value } } self.station_data = station_data def add(self, row): self.values.add(row[self.varcode]) def title(self): data = next(iter(self.station_data.values())) var = data.get(self.varcode, None) if var is None: value = "" else: value = var.format("") return "Station {}: {}".format(self.varcode, value) def column_labels(self): return ["Station {}".format(self.varcode)] def column_data(self, rec): id = rec["ana_id"] data = self.station_data[id] var = data.get(self.varcode, None) if var is None: return [""] else: return [var.format("")] class ColumnAttribute(Column): def __init__(self, varcode, attributes): super(ColumnAttribute, self).__init__() self.varcode = varcode # { "context_id,varcode": { varcode: value } } self.attributes = attributes def add(self, var): self.values.add(var.format("")) def title(self): data = next(iter(self.attributes.itervalues())) var = data.get(self.varcode, None) if var is None: value = "" else: value = var.format("") return "Attr {}: {}".format(self.varcode, value) def column_labels(self): return ["Attr {}".format(self.varcode)] def column_data(self, rec): data = self.attributes["{},{}".format(rec["context_id"], rec["var"])] var = data.get(self.varcode, None) if var is None: return [""] else: return [var.format("")] class Exporter: def __init__(self, db): self.db = db self.title = "" self.cols = [] # { Station id: { varcode: value } } self.station_data = {} # { "context_id,varcode": { varcode: value } } self.attributes = {} def compute_columns(self, filter): """ Compute what columns need to be in the output CSV. It queries DB-All.e once; another query will be needed later to output data. """ # Station data indexed by station id stations = {} # Do one pass over the result set to compute the columns columns = [ ColumnStation(stations), ColumnNetwork(), ColumnDatetime(), ColumnLevel(), ColumnTrange(), ColumnVar(), ColumnValue(), ] station_var_cols = {} attribute_cols = {} rowcount = 0 for row in self.db.query_data(filter): rowcount += 1 # Let the columns examine this row for c in columns: c.add(row) # Index station data by ana_id id = row["ana_id"] stations[id] = [row["lat"], row["lon"], row.get("ident", None)] # Load station variables for this station if id not in self.station_data: query = dballe.Record(ana_id=id) items = {} for record in self.db.query_station_data(query): v = record.var(record["var"]) items[v.code] = v col = station_var_cols.get(v.code, None) if col is None: station_var_cols[v.code] = col = ColumnStationData(v.code, self.station_data) col.add(record) self.station_data[id] = items # Load attributes attributes = {} for key, v in self.db.attr_query_data(row["context_id"]).varitems(): code = v.code attributes[code] = v col = attribute_cols.get(code, None) if col is None: attribute_cols[code] = col = ColumnAttribute(code, self.attributes) col.add(v) self.attributes["{},{}".format(row["context_id"], row["var"])] = attributes self.rowcount = rowcount # Now that we have detailed info, compute the columns # Build a list of all candidate columns all_columns = [] all_columns.extend(columns) for k, v in sorted(station_var_cols.items()): all_columns.append(v) for k, v in sorted(attribute_cols.items()): all_columns.append(v) # Dispatch them between title and csv body self.title_columns = [] self.csv_columns = [] for col in all_columns: if col.is_single_val(): self.title_columns.append(col) else: self.csv_columns.append(col) def output(self, query, fd): """ Perform a DB-All.e query using the given query and output the results in CSV format on the given file object """ if sys.version_info[0] >= 3: writer = csv.writer(fd, dialect="excel") else: writer = UnicodeCSVWriter(fd) self.compute_columns(query) # Don't query an empty result set if self.rowcount == 0: print("Result is empty.", file=sys.stderr) return row_headers = [] for c in self.csv_columns: row_headers.extend(c.column_labels()) # Print the title if we have it if self.title_columns: title = "; ".join(c.title() for c in self.title_columns) row = ["" for x in row_headers] row[0] = title writer.writerow(row) # Print the column headers writer.writerow(row_headers) for rec in self.db.query_data(query): row = [] for c in self.csv_columns: row.extend(c.column_data(rec)) writer.writerow(row) def export(db, query, fd): """ Perform a DB-All.e query using the given db and query query, and output the results in CSV format on the given file object """ e = Exporter(db) e.output(query, fd) dballe-7.7/python/dballe/volnd.py0000644000175000017500000005452212652630043014004 00000000000000#!/usr/bin/python # -*- coding: UTF-8 -*- """ volnd is an easy way of extracting entire matrixes of data out of a DB-All.e database. This module allows to extract multidimensional matrixes of data given a list of dimension definitions. Every dimension definition defines what kind of data goes along that dimension. Dimension definitions can be shared across different extracted matrixes and multiple extractions, allowing to have different matrixes whose indexes have the same meaning. This example code extracts temperatures in a station by datetime matrix:: query = dballe.Record() query["var"] = "B12001" query["rep_memo"] = "synop" query["level"] = (105, 2) query["trange"] = (0,) vars = read(self.db.query(query), (AnaIndex(), DateTimeIndex())) data = vars["B12001"] # Data is now a 2-dimensional Masked Array with the data # # Information about what values correspond to an index in the various # directions can be accessed in data.dims, which contains one list per # dimension with all the information corresponding to every index. print("Ana dimension is", len(data.dims[0]), "items long") print("Datetime dimension is", len(data.dims[1]), "items long") print("First 10 stations along the Ana dimension:", data.dims[0][:10]) print("First 10 datetimes along the DateTime dimension:", data.dims[1][:10]) """ # TODO: aggiungere metodi di query negli indici (eg. qual'è l'indice di questo # ana_id?) # TODO: leggere i dati di anagrafica from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import dballe from collections import namedtuple import datetime import sys import warnings # # * Dati # # Input: # - elenco di dimensioni interessanti # # Output: # - una matrice multidimensionale per variabile, con dentro i dati # - un vettore per dimensione, corrispondente alla lunghezza della matrice in # quella dimensione, con i dati su quella dimensione relativi a quel punto # della matrice. Nel caso dell'anagrafica, per esempio, questo vettore dice # lat,lon,ident,ana_id di ogni dato nella fetta di matrice tagliata in quel # punto. # # Integrando in provami, posso sapere in anticipo il numero di livelli etc # perché lo calcolo comunque per i menu # # Sincronizzate tra le varie matrici: # - ana, data # Vettori diversi per ogni matrice: # - livello, scadenza # import os if os.environ.get("DBALLE_BUILDING_DOCS", "") != 'true': import numpy import numpy.ma as ma # Alternative hack to run without numpy's C code #from . import tinynumpy as numpy #class ma: # @classmethod # def array(cls, a, *args, **kw): # return a class SkipDatum(Exception): pass class Index(object): """ Base class for all volnd indices. An Index describes each entry along one dimension of a volnd volume. There is an entry in the index for each point along that axis, and each entry can be an arbitrary structure with details. Index objects can be shared between homogeneous volumes. """ def __init__(self, shared=True, frozen=False): self._shared = shared self._frozen = frozen def freeze(self): """ Set the index as frozen: indexing elements not already in the index will raise a SkipDatum exception """ self._frozen = True def copy(self): """ Return another version of this index: it can be a reference to the exact same index if shared=True; otherwise it's a new, empty version. """ if self._shared: return self else: return self.__class__() class ListIndex(Index, list): """ Indexes records along an axis. Each index entry is an arbitrary details structure extracted from records. All records at a given index position will have the same details. """ def __init__(self, shared=True, frozen=False, start=None): super(ListIndex, self).__init__(shared, frozen) # Maps indexing keys to list positions # A key is a short, unique version of the details. Details can be # thought as verbose, useful versions of keys. self._map = {} if start: for el in start: id, val = self._splitInit(el) self._map[id] = len(self) self.append(val) def __str__(self): return self.short_name() + ": " + list.__str__(self) def key_from_record(self, rec): "Extract the indexing key from the record" return None def details_from_record(self, rec): "Extract the full data information from the record" return None def _splitInit(self, el): """ Extract the indexing key and full data information from one of the objects passed as the start= value to the constructor to preinit an index """ return el, el def approve(self, rec): """ Return true if the record can be placed along this index """ if not self._frozen: return True return self.key_from_record(rec) in self._map def index_record(self, rec): """ Return an integer index along this axis for the given record """ key = self.key_from_record(rec) pos = self._map.get(key, None) if pos is None: self._map[key] = pos = len(self) self.append(self.details_from_record(rec)) return pos class AnaIndexEntry(namedtuple("AnaIndexEntry", ("id", "lat", "lon", "ident"))): """ AnaIndex entry, with various data about a single station. It is a named tuple of 4 values: * id: station id * lat: latitude * lon: longitude * ident: mobile station identifier, or None """ @classmethod def from_record(cls, rec): """ Create an index entry from the contents of a dballe.Record """ return cls(rec["ana_id"], rec["lat"], rec["lon"], rec.get("ident", None)) def __str__(self): if self[3] == None: return "Station at lat %.5f lon %.5f" % (self.lat, self.lon) else: return "%s at lat %.5f lon %.5f" % (self.ident, self.lat, self.lon) def __repr__(self): return "AnaIndexEntry" + tuple.__repr__(self) class AnaIndex(ListIndex): """ Index for stations, as they come out of the database. The constructor syntax is: ``AnaIndex(shared=True, frozen=False, start=None)``. The index saves all stations as AnaIndexEntry tuples, in the same order as they come out of the database. """ def key_from_record(self, rec): return rec["ana_id"] def details_from_record(self, rec): return AnaIndexEntry.from_record(rec) def _splitInit(self, el): return el[0], el def short_name(self): return "AnaIndex["+str(len(self))+"]" class NetworkIndex(ListIndex): """ Index for networks, as they come out of the database. The constructor syntax is: ``NetworkIndex(shared=True, frozen=False, start=None)``. The index saves all networks as NetworkIndexEntry tuples, in the same order as they come out of the database. """ def key_from_record(self, rec): return rec["rep_memo"] def details_from_record(self, rec): return rec["rep_memo"] def _splitInit(self, el): return el[0], el def short_name(self): return "NetworkIndex["+str(len(self))+"]" class LevelIndex(ListIndex): """ Index for levels, as they come out of the database The constructor syntax is: ``LevelIndex(shared=True, frozen=False), start=None``. The index saves all levels as dballe.Level tuples, in the same order as they come out of the database. """ def key_from_record(self, rec): # Suppress deprecation warnings until we have something better with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) return rec["level"] def details_from_record(self, rec): return self.key_from_record(rec) def short_name(self): return "LevelIndex["+str(len(self))+"]" class TimeRangeIndex(ListIndex): """ Index for time ranges, as they come out of the database. The constructor syntax is: ``TimeRangeIndex(shared=True, frozen=False, start=None)``. The index saves all time ranges as dballe.TimeRange tuples, in the same order as they come out of the database. """ def key_from_record(self, rec): # Suppress deprecation warnings until we have something better with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) return rec["trange"] def details_from_record(self, rec): return self.key_from_record(rec) def short_name(self): return "TimeRangeIndex["+str(len(self))+"]" class DateTimeIndex(ListIndex): """ Index for datetimes, as they come out of the database. The constructor syntax is: ``DateTimeIndex(shared=True, frozen=False, start=None)``. The index saves all datetime values as datetime.datetime objects, in the same order as they come out of the database. """ def key_from_record(self, rec): # Suppress deprecation warnings until we have something better with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) return rec["date"] def details_from_record(self, rec): return self.key_from_record(rec) def short_name(self): return "DateTimeIndex["+str(len(self))+"]" def tddivmod1(td1, td2): "Division and quotient between time deltas" if td2 > td1: return 0, td1 if td2 == 0: raise ZeroDivisionError("Dividing by a 0 time delta") mults = (86400, 1000000, 1) n1 = (td1.days, td1.seconds, td1.microseconds) n2 = (td2.days, td2.seconds, td2.microseconds) d = 0 q = 0 for i in range(3): d += n1[i] if d != 0: if n2[i] == 0: d *= mults[i] else: q = d // n2[i] break else: if n2[i] == 0: pass else: break t = td2 * q if t > td1: q = q - 1 return q, td1 - td2 * q else: return q, td1 - t def tddivmod2(td1, td2): """ Division and quotient between time deltas (alternate implementation using longs) """ std1 = td1.days*(3600*24*1000000) + td1.seconds*1000000 + td1.microseconds std2 = td2.days*(3600*24*1000000) + td2.seconds*1000000 + td2.microseconds q = std1 // std2 return q, td1 - (td2 * q) # Choose which implementation to use if sys.version_info[0] >= 3: def tddivmod3(td1, td2): return td1 // td2, td1 % td2 tddivmod = tddivmod3 else: tddivmod3 = None tddivmod = tddivmod2 class IntervalIndex(Index): """ Index into equally spaced points in time, starting at ``start``, with a point every ``step`` time. Index points are at fixed time intervals, and data is acquired in one point only if it is within a given tolerance from the interval. The constructor syntax is: ``IntervalIndex(start, step, tolerance=0, end=None, shared=True, frozen=False)``. ``start`` is a datetime.datetime object giving the starting time of the time interval of this index. ``step`` is a datetime.timedelta object with the interval between sampling points. ``tolerance`` is a datetime.timedelta object specifying the maximum allowed interval between a datum datetime and the sampling step. If the interval is bigger than the tolerance, the data is discarded. ``end`` is an optional datetime.datetime object giving the ending time of the time interval of the index. If omitted, the index will end at the latest accepted datum coming out of the database. """ def __init__(self, start, step, tolerance=0, end=None, *args, **kwargs): """ start is a datetime with the starting moment step is a timedelta with the interval between times tolerance is a timedelta specifying how much skew a datum is allowed to have from a sampling moment """ super(IntervalIndex, self).__init__(*args, **kwargs) self._start = start self._step = step self._end = end if end != None: self._size = (end-start)/step else: self._size = 0 self._tolerance = datetime.timedelta(0) def approve(self, rec): t = rec["date"] # Skip all entries before the start if t < self._start: return False if self._end and t > self._end: return False # With integer division we get both the position and the skew pos, skew = tddivmod(t - self._start, self._step) if skew > self._step / 2: pos += 1 skew = skew - self._step if skew > self._tolerance: return False if self._frozen and pos >= self._size: return False return True def index_record(self, rec): t = rec["date"] # With integer division we get both the position and the skew pos, skew = tddivmod(t - self._start, self._step) if skew > self._step / 2: pos += 1 if pos >= self._size: self._size = pos + 1 return pos def __len__(self): return self._size def __iter__(self): for i in range(self._size): yield self._start + self._step * i def __str__(self): return self.short_name() + ": " + ", ".join(self) def short_name(self): return "IntervalIndex["+str(self._size)+"]" def copy(self): if self._shared: return self else: return IntervalIndex(self._start, self._step, self._tolerance, self._end) class Data: """ Container for collecting variable data. It contains the variable data array and the dimension indexes. If v is a Data object, you can access the tuple with the dimensions as v.dims, and the masked array with the values as v.vals. """ def __init__(self, name, dims, checkConflicts=True): """ name = name of the variable (eg. "B12001") dims = list of Index objects one for every dimension if checkConflicts is True, then an exception is raised if two output values would end up filling the same matrix element """ # Variable name, as a B table entry (e.g. "B12001") self.name = name # Tuple with all the dimension Index objects self.dims = dims # After finalise() has been called, it is the masked array with # all the values. Before calling finalise(), it is the list of # collected data. self.vals = [] # Maps attribute names to Data objects with the attribute # values. The dimensions of the Data objects are fully # synchronised with this one. self.attrs = {} # Information about the variable self.info = dballe.varinfo(name) self._checkConflicts = checkConflicts self._lastPos = None def append(self, rec): """ Collect a new value from the given dballe record. You need to call finalise() before the values can be used. """ accepted = all(dim.approve(rec) for dim in self.dims) if accepted: # Obtain the index for every dimension pos = tuple(dim.index_record(rec) for dim in self.dims) # Save the value with its indexes self.vals.append( (pos, rec[self.name]) ) # Save the last position for appendAttrs self._lastPos = pos return True else: # If the value cannot be mapped along this dimension, # skip it self._lastPos = None return False def appendAttrs(self, rec, codes=None): """ Collect attributes to append to the record. You need to call finalise() before the values can be used. """ if not self._lastPos: return for code in rec: if codes is not None and code not in codes: continue #print "Attr", var.code(), "for", self.name, "at", self._lastPos if code in self.attrs: data = self.attrs[code] else: data = Data(self.name, self.dims, False) self.attrs[code] = data # Append at the same position as the last variable # collected data.vals.append((self._lastPos, rec[code])) def _instantiateIntMatrix(self): shape = tuple(len(d) for d in self.dims) if self.info.bit_ref == 0: # bit_ref is 0, so we are handling unsigned # numbers and we know the exact number of bits # used for encoding bits = self.info.bit_len if bits <= 8: #print 'uint8' a = numpy.empty(shape, dtype='uint8') elif bits <= 16: #print 'uint16' a = numpy.empty(shape, dtype='uint16') elif bits <= 32: #print 'uint32' a = numpy.empty(shape, dtype='uint32') else: #print 'uint64' a = numpy.empty(shape, dtype='uint64') else: # We have a bit_ref, so we can have negative # values or we can have positive values bigger # than usual (for example, for negative bit_ref # values). Therefore, choose the size of the # int in the matrix according to the value # range instead of bit_len() range = self.info.imax - self.info.imin #print self.info, range if range < 256: #print 'int8' a = numpy.empty(shape, dtype='int8') elif range < 65536: #print 'int16' a = numpy.empty(shape, dtype='int16') elif range <= 4294967296: #print 'int32' a = numpy.empty(shape, dtype='int32') else: a = numpy.empty(shape, dtype=int) return a def finalise(self): """ Stop collecting values and create a masked array with all the values collected so far. """ # If one of the dimensions is empty, we don't have any valid data if any(len(d) == 0 for d in self.dims): return False shape = tuple(len(x) for x in self.dims) # Create the data array, with all values set as missing #print "volnd finalise instantiate" if self.info.type == "string": #print self.info, "string" a = numpy.empty(shape, dtype=object) # Fill the array with all the values, at the given indexes for pos, val in self.vals: if self._checkConflicts and a[pos] is not None: raise IndexError("Got more than one value for " + self.name + " at position " + str(pos)) a[pos] = val else: if self.info.type == "integer": a = self._instantiateIntMatrix() else: a = numpy.empty(shape, dtype=numpy.float64) mask = numpy.ones(shape, dtype=numpy.bool) # Fill the array with all the values, at the given indexes for pos, val in self.vals: if self._checkConflicts and not mask[pos]: raise IndexError("Got more than one value for " + self.name + " at position " + str(pos)) a[pos] = val mask[pos] = False a = ma.array(a, mask=mask) # Replace the intermediate data with the results self.vals = a # Finalise all the attributes as well #print "volnd finalise fill" invalid = [] for key, d in self.attrs.items(): if not d.finalise(): invalid.append(key) # Delete empty attributes for k in invalid: del self.addrs[k] return True def __str__(self): return "Data("+", ".join(x.short_name() for x in self.dims)+"):"+str(self.vals) def __repr__(self): return "Data("+", ".join(x.short_name() for x in self.dims)+"):"+self.vals.__repr__() def read(cursor, dims, filter=None, checkConflicts=True, attributes=None): """ *cursor* is a dballe.Cursor resulting from a dballe query *dims* is the sequence of indexes to use for shaping the data matrixes *filter* is an optional filter function that can be used to discard values from the query: if filter is not None, it will be called for every output record and if it returns False, the record will be discarded *checkConflicts* tells if we should raise an exception if two values from the database would fill in the same position in the matrix *attributes* tells if we should read attributes as well: if it is None, no attributes will be read; if it is True, all attributes will be read; if it is a sequence, then it is the sequence of attributes that should be read. """ ndims = len(dims) vars = {} #print "volnd iterate" # Iterate results for rec in cursor: # Discard the values that filter does not like if filter and not filter(rec): continue varname = rec["var"] # Instantiate the index objects here for every variable # when it appears the first time, sharing those indexes that # need to be shared and creating new indexes for the individual # ones if varname not in vars: var = Data(varname, [x.copy() for x in dims], checkConflicts) vars[varname] = var else: var = vars[varname] # Save every value with its indexes if not var.append(rec): continue # Add the attributes if attributes != None: arec = cursor.attr_query(); if attributes == True: var.appendAttrs(arec) else: var.appendAttrs(arec, attributes) # Now that we have collected all the values, create the arrays #print "volnd finalise" invalid = [] for k, var in vars.items(): if not var.finalise(): invalid.append(k) for k in invalid: del vars[k] return vars dballe-7.7/python/dballe/rconvert.py0000644000175000017500000000522212652630043014515 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import os import itertools if os.environ.get("DBALLE_BUILDING_DOCS", "") != 'true': import numpy import numpy.ma as ma #import Numeric as numeric import rpy2.robjects as robjects import rpy2.rinterface as rinterface # Failed experiment: the __dict__ of MaskedArray is a dictproxy instance that # is read-only #dballe.volnd.Data.__dict__['as_r'] = new.instancemethod(fun, None, dballe.volnd.Data) #def genfloat(a): # for x in a.flat: # if ma.getmask(x) != 1: # yield float(x) # else: # yield robjects.r.NAN def ma_to_rlist(arr): """ Create a list of floats or rinterface.NA_Real from a masked array, raveled in R value order """ ma_data = arr.data.ravel("F") ma_mask = arr.mask.ravel("F") rlist = [] for val, mask in zip(ma_data, ma_mask): if mask: rlist.append(rinterface.NA_Real) else: rlist.append(val) return rlist def ma_to_r(arr, dimnames=None): """ Convert a Masked Array to an R object """ # We copy data around way more than we probably should, but I found no way # to efficiently generate R NA values from a the MaskedArray mask # Convert to floats farray = ma.array(arr, dtype=float) # Convert to an R array, with NAs vec = rinterface.FloatSexpVector(ma_to_rlist(farray)) dim = rinterface.IntSexpVector(farray.shape) if dimnames: # Create with dimension names, too dimnames = robjects.r.array(dimnames) farray = robjects.r.array(vec, dim=dim, dimnames=dimnames) else: farray = robjects.r.array(vec, dim=dim) return farray def volnd_data_to_r(data): """ Convert a volnd data object to an R object """ rinterface.initr() dn = [] for i in data.dims: dn.append([str(x) for x in i]) return ma_to_r(data.vals, dimnames=dn) def volnd_save_to_r(vars, file): """ Convert the result of a volnd read into various R objects, and save them to the given file """ rinterface.initr() tosave = [] for k, d in vars.items(): #print "s2r", k robjects.r.assign(k, volnd_data_to_r(d)) tosave.append(k) for aname, adata in d.attrs.items(): robjects.r.assign(k+"."+aname, volnd_data_to_r(adata)) tosave.append(k+"."+aname) tosave = robjects.vectors.StrVector(tosave) robjects.r.save(list=tosave, file=file) # Cleanup the names from the environment robjects.r.remove(list=tosave) dballe-7.7/python/dballe/__init__.py0000644000175000017500000000020612652630043014407 00000000000000from __future__ import absolute_import import wreport from wreport import Var, Varinfo, Vartable import _dballe from _dballe import * dballe-7.7/python/test-core.py0000755000175000017500000000077112652630043013344 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import dballe import unittest class Describe(unittest.TestCase): def testLevel(self): self.assertIn("surface", dballe.describe_level(1)) def testTrange(self): self.assertIn("Accumulation", dballe.describe_trange(1)) if __name__ == "__main__": from testlib import main main("test_core") dballe-7.7/python/cursor.h0000644000175000017500000000277012652630043012551 00000000000000/* * python/cursor - DB-All.e DB cursor python bindings * * Copyright (C) 2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_PYTHON_CURSOR_H #define DBALLE_PYTHON_CURSOR_H #include #include #include "record.h" #include "db.h" extern "C" { typedef struct { PyObject_HEAD dpy_DB* db; dballe::db::Cursor* cur; dpy_Record* rec; } dpy_Cursor; PyAPI_DATA(PyTypeObject) dpy_Cursor_Type; #define dpy_Cursor_Check(ob) \ (Py_TYPE(ob) == &dpy_Cursor_Type || \ PyType_IsSubtype(Py_TYPE(ob), &dpy_Cursor_Type)) } namespace dballe { namespace python { /** * Create a new dpy_Cursor, taking ownership of memory management */ dpy_Cursor* cursor_create(dpy_DB* db, std::unique_ptr cur); void register_cursor(PyObject* m); } } #endif dballe-7.7/python/db.h0000644000175000017500000000321112652630043011610 00000000000000/* * python/db - DB-All.e DB python bindings * * Copyright (C) 2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_PYTHON_DB_H #define DBALLE_PYTHON_DB_H #include #include #include "record.h" extern "C" { typedef struct { PyObject_HEAD dballe::DB* db; dpy_Record* attr_rec; } dpy_DB; PyAPI_DATA(PyTypeObject) dpy_DB_Type; #define dpy_DB_Check(ob) \ (Py_TYPE(ob) == &dpy_DB_Type || \ PyType_IsSubtype(Py_TYPE(ob), &dpy_DB_Type)) } namespace dballe { namespace python { /** * Create a new dpy_DB, taking over memory management */ dpy_DB* db_create(std::unique_ptr db); /** * Copy varcodes from a Python sequence to a db::AttrList */ int db_read_attrlist(PyObject* attrs, db::AttrList& codes); void register_db(PyObject* m); bool db_load_fileobj(DB* db, PyObject* obj); bool db_load_filelike(DB* db, PyObject* obj); bool db_load_fileno(DB* db, PyObject* obj); } } #endif dballe-7.7/Makefile.in0000644000175000017500000010115012652630066011604 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @DO_DBALLEF_TRUE@am__append_1 = fortran @DO_DOCS_TRUE@am__append_2 = doc @DO_DBALLE_PYTHON_TRUE@am__append_3 = python subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/m4_ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = libdballe.pc libdballef.pc CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(m4dir)" \ "$(DESTDIR)$(pkgconfigdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(m4_DATA) $(pkgconfig_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir 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, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = tables dballe extra src fortran doc python . am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(srcdir)/libdballe.pc.in $(srcdir)/libdballef.pc.in ChangeLog \ README TODO compile config.guess config.sub install-sh \ ltmain.sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FC = @FC@ FCFLAGS = @FCFLAGS@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDBALLEF_VERSION_INFO = @LIBDBALLEF_VERSION_INFO@ LIBDBALLE_VERSION_INFO = @LIBDBALLE_VERSION_INFO@ LIBOBJS = @LIBOBJS@ LIBPQ_CFLAGS = @LIBPQ_CFLAGS@ LIBPQ_LIBS = @LIBPQ_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ WREPORT_CFLAGS = @WREPORT_CFLAGS@ WREPORT_LIBS = @WREPORT_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_FC = @ac_ct_FC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_doxygen = @have_doxygen@ have_gperf = @have_gperf@ have_latex2html = @have_latex2html@ have_rst2html = @have_rst2html@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mysql_config = @mysql_config@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ tabledir = @tabledir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = tables dballe extra src $(am__append_1) $(am__append_2) \ $(am__append_3) . #examples pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libdballe.pc libdballef.pc m4dir = $(datadir)/aclocal m4_DATA = libdballe.m4 libdballef.m4 man_MANS = dbatbl.1 dbamsg.1 dbadb.1 dbaexport.1 BUILT_SOURCES = dbaexport.1 EXTRA_DIST = LICENSE BENCHMARKS ODBC-TRACE-HOWTO autogen.sh \ libdballe.m4 libdballef.m4 \ libdballe.pc.in libdballef.pc.in \ $(conf_DATA) get_line_no run-check.conf.example \ run-check run-local run-bench show_code_notes \ UPGRADE-5.x \ dbaexport.1 \ fedora/SPECS/dballe.spec CLEANFILES = dbatbl.1 dbamsg.1 dbadb.1 all: $(BUILT_SOURCES) config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 libdballe.pc: $(top_builddir)/config.status $(srcdir)/libdballe.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libdballef.pc: $(top_builddir)/config.status $(srcdir)/libdballef.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-m4DATA: $(m4_DATA) @$(NORMAL_INSTALL) @list='$(m4_DATA)'; test -n "$(m4dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(m4dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(m4dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(m4dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(m4dir)" || exit $$?; \ done uninstall-m4DATA: @$(NORMAL_UNINSTALL) @list='$(m4_DATA)'; test -n "$(m4dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(m4dir)'; $(am__uninstall_files_from_dir) install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @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 $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(MANS) $(DATA) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(m4dir)" "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-m4DATA install-man install-pkgconfigDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man1 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-m4DATA uninstall-man uninstall-pkgconfigDATA uninstall-man: uninstall-man1 .MAKE: $(am__recursive_targets) all check install install-am \ install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip distcheck distclean distclean-generic \ distclean-hdr distclean-libtool distclean-tags distcleancheck \ distdir distuninstallcheck 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-m4DATA install-man install-man1 install-pdf \ install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am uninstall-m4DATA \ uninstall-man uninstall-man1 uninstall-pkgconfigDATA .PRECIOUS: Makefile dbadb.1: src/dbadb doc/add_templates_to_manpage ( cd src && ./`basename $<` help manpage ) | ( cd $(srcdir) && $(srcdir)/doc/add_templates_to_manpage ) > $@ dbamsg.1: src/dbamsg doc/add_templates_to_manpage ( cd src && ./`basename $<` help manpage ) | ( cd $(srcdir) && $(srcdir)/doc/add_templates_to_manpage ) > $@ dbaexport.1: src/dbaexport COLUMNS=200 help2man --name='export data from DB-All.e' --section=1 --no-info --version-string="$(PACKAGE_VERSION)" $< > $@ %.1: src/% ( cd src && ./`basename $<` help manpage ) > $@ # 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: dballe-7.7/src/0000755000175000017500000000000012653425051010405 500000000000000dballe-7.7/src/dbatbl.cc0000644000175000017500000003407212652630043012070 00000000000000#include #include #include #include #include #include #include #include #include #include "config.h" using namespace dballe; using namespace dballe::cmdline; using namespace wreport; using namespace std; int op_verbose = 0; /// Write CSV output to the given output stream struct FileCSV : CSVWriter { FILE* out; FileCSV(FILE* out) : out(out) {} void flush_row() override { fputs(row.c_str(), out); putc('\n', out); row.clear(); } }; struct VarinfoPrinter : public cmdline::Subcommand { int op_csv = 0; int op_crex = 0; CSVWriter* csv_out = nullptr; ~VarinfoPrinter() { delete csv_out; } void init() override { if (op_csv) csv_out = new FileCSV(stdout); } void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back(poptOption{ "csv", 'c', POPT_ARG_NONE, (void*)&op_csv, 0, "output variables in CSV format" }); opts.push_back(poptOption{ "crex", 0, POPT_ARG_NONE, (void*)&op_crex, 0, "read CREX entries instead of BUFR" }); } const Vartable* load_vartable(const char* id) { if (op_crex) return Vartable::load_crex(id); else return Vartable::load_bufr(id); } void print_varinfo(Varinfo info) const { if (csv_out) print_varinfo_csv(*csv_out, info); else print_varinfo_desc(info); } static std::string format_decimal(Varinfo info) { string res; if (info->scale > 0) { if (info->len > info->scale) for (unsigned i = 0; i < info->len - info->scale; ++i) res += '#'; res += '.'; for (unsigned i = 0; i < info->scale; ++i) res += '#'; } else if (info->scale < 0) { for (unsigned i = 0; i < info->len; ++i) res += '#'; for (unsigned i = 0; i < -info->scale; ++i) res += '0'; } return res; } static void print_varinfo_desc(Varinfo info) { switch (info->type) { case Vartype::String: printf("%d%02d%03d %s [%s, %u characters]\n", WR_VAR_FXY(info->code), info->desc, info->unit, info->len); break; case Vartype::Binary: printf("%d%02d%03d %s [%s, %u bits]\n", WR_VAR_FXY(info->code), info->desc, info->unit, info->bit_len); break; case Vartype::Integer: printf("%d%02d%03d %s [%s, %u digits] range (%d -- %d)\n", WR_VAR_FXY(info->code), info->desc, info->unit, info->len, info->imin, info->imax); break; case Vartype::Decimal: printf("%d%02d%03d %s [%s, %s] range (%g -- %g)\n", WR_VAR_FXY(info->code), info->desc, info->unit, format_decimal(info).c_str(), info->dmin, info->dmax); break; } } static void print_varinfo_csv(CSVWriter& out, const Varinfo& info) { out.add_value(varcode_format(info->code)); out.add_value(info->desc); out.add_value(info->unit); out.add_value(vartype_format(info->type)); switch (info->type) { case Vartype::String: out.add_value(info->len); out.add_value_empty(); out.add_value_empty(); break; case Vartype::Binary: out.add_value(info->bit_len); out.add_value_empty(); out.add_value_empty(); break; case Vartype::Integer: out.add_value(info->len); out.add_value(info->imin); out.add_value(info->imax); break; case Vartype::Decimal: out.add_value(format_decimal(info)); out.add_value(to_string(info->dmin)); out.add_value(to_string(info->dmax)); break; } out.flush_row(); } }; struct Cat : public VarinfoPrinter { Cat() { names.push_back("cat"); usage = "cat tableid [tableid [...]]"; desc = "Output all the contents of a WMO B table."; } int main(poptContext optCon) override { const char* item; /* Throw away the command name */ poptGetArg(optCon); if (poptPeekArg(optCon) == NULL) item = "dballe"; else item = poptGetArg(optCon); while (item != NULL) { const Vartable* table = load_vartable(item); table->iterate([&](Varinfo info) { print_varinfo(info); return true; }); item = poptGetArg(optCon); } return 0; } }; struct Grep : public VarinfoPrinter { Grep() { names.push_back("grep"); usage = "grep string"; desc = "Output all the contents of the local B table whose description contains the given string."; } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); if (poptPeekArg(optCon) == NULL) dba_cmdline_error(optCon, "there should be at least one B or D item to expand. Examples are: B01002 or D03001"); const char* pattern = poptGetArg(optCon); const Vartable* table = load_vartable("dballe"); table->iterate([&](Varinfo info) { #if HAVE_STRCASESTR if (strcasestr(info->desc, pattern) != NULL) #else #warning dbatbl grep is case sensite on this sytstem, since strcasestr is not available if (strstr(info->desc, pattern) != NULL) #endif print_varinfo(info); return true; }); return 0; } }; #if 0 struct Expand : public cmdline::Subcommand { const Vartable* btable = NULL; const DTable* dtable = NULL; Expand() { names.push_back("expand"); usage = "expand table-entry [table-entry [...]]"; desc = "Describe a WMO B table entry or expand a WMO D table entry in its components."; } int main(poptContext optCon) override { const char* item; /* Throw away the command name */ poptGetArg(optCon); btable = Vartable::get("dballe"); dtable = DTable::get("D000203"); if (poptPeekArg(optCon) == NULL) dba_cmdline_error(optCon, "there should be at least one B or D item to expand. Examples are: B01002 or D03001"); while ((item = poptGetArg(optCon)) != NULL) expand_table_entry(descriptor_code(item), 0); return 0; } void expand_table_entry(Varcode val, int level) { int i; for (i = 0; i < level; i++) printf("\t"); switch (WR_VAR_F(val)) { case 0: { Varinfo info = btable->query(val); VarinfoPrinter::print_varinfo_desc(info); break; } case 3: { Opcodes ops = dtable->query(val); printf("%d%02d%03d\n", WR_VAR_F(val), WR_VAR_X(val), WR_VAR_Y(val)); for (size_t i = 0; i < ops.size(); ++i) expand_table_entry(ops[i], level+1); break; } default: printf("%d%02d%03d\n", WR_VAR_F(val), WR_VAR_X(val), WR_VAR_Y(val)); } } }; #endif struct ExpandCode : public cmdline::Subcommand { ExpandCode() { names.push_back("expandcode"); usage = "expandcode varcode [varcode [...]]"; desc = "Expand the value of a packed variable code"; } int main(poptContext optCon) override { const char* item; /* Throw away the command name */ poptGetArg(optCon); while ((item = poptGetArg(optCon)) != NULL) { int code = strtol(item, NULL, 10); char c = 'B'; switch (WR_VAR_F(code)) { case 0: c = 'B'; break; case 1: c = 'R'; break; case 2: c = 'C'; break; case 3: c = 'D'; break; } printf("%s: %c%02d%03d\n", item, c, WR_VAR_X(code), WR_VAR_Y(code)); } return 0; } }; #if 0 static const char* table_type = "b"; struct Index : public cmdline::Subcommand { Index() { names.push_back("index"); usage = "index [options] filename index-id"; desc = "Index the contents of a table file"; } void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back({ "type", 't', POPT_ARG_STRING, &table_type, 0, "format of the table to index ('b', 'd', 'conv')", "type" }); } /** * Check that all unit conversions are allowed by dba_uniconv * * @returns true if all conversions worked, false if some exceptions were thrown */ static bool check_unit_conversions(const char* id) { const Vartable* othertable = Vartable::get(id); bool res = true; for (Vartable::const_iterator info = othertable->begin(); info != othertable->end(); ++info) { Varcode varcode = info->var; /* if (var % 1000 == 0) fprintf(stderr, "Testing %s %d\n", ids[i], var); */ if (varcode != 0 && !info->is_string()) { try { Varinfo local = varinfo(varcode); convert_units(info->unit, local->unit, 1.0); } catch (std::exception& e) { fprintf(stderr, "Checking conversion for var B%02d%03d: %s", WR_VAR_X(varcode), WR_VAR_Y(varcode), e.what()); res = false; } } } return res; } int main(poptContext optCon) override { const char* file; const char* id; /* Throw away the command name */ poptGetArg(optCon); file = poptGetArg(optCon); id = poptGetArg(optCon); if (file == NULL) dba_cmdline_error(optCon, "input file has not been specified"); if (id == NULL) dba_cmdline_error(optCon, "indexed table ID has not been specified"); if (strcmp(table_type, "b") == 0) { if (strcmp(id, "dballe") != 0) { /* If it's an external table, check unit conversions to DBALLE * correspondents */ if (!check_unit_conversions(id)) fprintf(stderr, "Warning: some variables cannot be converted from %s to dballe\n", id); } } else if (strcmp(table_type, "d") == 0) ; /* DBA_RUN_OR_RETURN(bufrex_dtable_index(file, id)); */ /* else if (strcmp(type, "conv") == 0) DBA_RUN_OR_RETURN(bufrex_convtable_index_csv(file, id)); */ else dba_cmdline_error(optCon, "'%s' is not a valid table type", table_type); return 0; } }; #endif struct Describe : public cmdline::Subcommand { Describe() { names.push_back("describe"); usage = "describe [options] what [values]"; desc = "Invoke the formatter to describe the given values"; longdesc = "Supported so far are: \"level ltype l1 l2\", \"trange pind p1 p2\""; } int main(poptContext optCon) override { const char* what; /* Throw away the command name */ poptGetArg(optCon); if ((what = poptGetArg(optCon)) == NULL) dba_cmdline_error(optCon, "you need to specify what you want to describe. Available options are: 'level' and 'trange'"); if (strcmp(what, "level") == 0) { const char* sltype1 = poptGetArg(optCon); const char* sl1 = poptGetArg(optCon); const char* sltype2 = poptGetArg(optCon); const char* sl2 = poptGetArg(optCon); if (sltype1 == NULL) dba_cmdline_error(optCon, "you need provide 1, 2, 3 or 4 numbers that identify the level or layer"); string formatted = Level( strtoul(sltype1, NULL, 10), sl1 == NULL ? 0 : strtoul(sl1, NULL, 10), sltype2 == NULL ? 0 : strtoul(sltype2, NULL, 10), sl2 == NULL ? 0 : strtoul(sl2, NULL, 10)).describe(); puts(formatted.c_str()); } else if (strcmp(what, "trange") == 0) { const char* sptype = poptGetArg(optCon); const char* sp1 = poptGetArg(optCon); const char* sp2 = poptGetArg(optCon); if (sptype == NULL) dba_cmdline_error(optCon, "you need provide 1, 2 or 3 numbers that identify the time range"); string formatted = Trange( strtoul(sptype, NULL, 10), sp1 == NULL ? 0 : strtoul(sp1, NULL, 10), sp2 == NULL ? 0 : strtoul(sp2, NULL, 10)).describe(); puts(formatted.c_str()); } else dba_cmdline_error(optCon, "cannot handle %s. Available options are: 'level' and 'trange'.", what); return 0; } }; int main(int argc, const char* argv[]) { Command dbatbl; dbatbl.name = "dbatbl"; dbatbl.desc = "Manage on-disk reference tables for DB-ALLe"; dbatbl.longdesc = "This tool allows to index and query the tables that are " "needed for normal functioning of DB-ALLe"; dbatbl.add_subcommand(new Cat); dbatbl.add_subcommand(new Grep); //dbatbl.add_subcommand(new Expand); dbatbl.add_subcommand(new ExpandCode); //dbatbl.add_subcommand(new Index); dbatbl.add_subcommand(new Describe); return dbatbl.main(argc, argv); } dballe-7.7/src/dbatbl_makeb0000755000175000017500000002231212652630043012640 00000000000000#!/usr/bin/python import struct import sys # Documentation for Entry fields ENTRYDOC = { "var": "The variable code (BXXYYY)", "desc": "The variable description (max 64 chars)", "unit": "The measurement unit of the variable (max 64 chars)", "scale": "The scale of the variable. When the variable is represented as an integer, it is multiplied by 10**scale", "ref": "The reference value for the variable. When the variable is represented as an integer, and after scaling, it is added this value", "len": "The length in digits of the integer representation of this variable (after scaling and changing reference value)", "bit_ref": "The reference value for bit-encoding. When the variable is encoded in a bit string, it is added this value", "bit_len": "The length in bits of the variable when encoded in a bit string (after scaling and changing reference value)", "bufr_unit": "The measurement unit of the variable when encoded in BUFR. (max 24 chars)", "bufr_scale": "The scale of the variable when encoded in BUFR.", } def unit_is_string(unit): # if unit.startswith("CODE TABLE"): return True return unit in ["CCITTIA5", "CHARACTER"] class Entry(object): "A B table entry" FIELDS=["var", "desc", "unit", "scale", "ref", "len", "bit_ref", "bit_len", "bufr_unit", "bufr_scale"] NUMFIELDS=["scale", "ref", "len", "bit_ref", "bit_len", "bufr_scale"] def __init__(self): self.var = "B00000" self.desc = "" self.unit = "" self.scale = 0 self.ref = -10 self.len = 0 self.bit_ref = -10 self.bit_len = 0 self.bufr_unit = "" self.bufr_scale = 0 ## Minimum unscaled value the field can have #self.imin ## Maximum unscaled value the field can have #int imax; ## Minimum scaled value the field can have #double dmin; ## Maximum scaled value the field can have #double dmax; BUFRFMT='x6sx64sx24sx3sx12sx3s' def read_bufr(self, s): "Read from the bufr part of the B table" self.var, self.desc, self.unit, self.scale, self.bit_ref, self.bit_len = struct.unpack(self.BUFRFMT, s[:118]) if self.var[0] == '0': self.var = 'B' + self.var[1:] self.scale = int(self.scale) self.bit_ref = int(self.bit_ref) self.bit_len = int(self.bit_len) self.desc = self.desc.strip() self.unit = self.unit.strip() self.bufr_unit = self.unit self.bufr_scale = self.scale # Compute character length from bit lenght if unit_is_string(self.unit): self.len = self.bit_len / 8 else: tlen = 1 << self.bit_len self.len = 0 while tlen != 0: tlen = tlen / 10 self.len += 1 CREXFMT='24sx2sx10s' def read_crex(self, s): self.unit, self.scale, self.len = struct.unpack(self.CREXFMT, s[:38]) self.unit = self.unit.strip() self.scale = int(self.scale) self.len = int(self.len) FMT=" %-6.6s %-64.64s %-24.24s %3.3s %12.12s %3.3s %-24.24s %2.2s %10.10s" def encode(self): var = self.var if var[0] == 'B': var = '0' + var[1:] args = map(str, (var, self.desc, self.unit, self.scale, self.bit_ref, self.bit_len, self.unit, self.scale, self.len)) return self.FMT % tuple(args) def dump(self): print "Var:", self.var print "Desc:", self.desc if self.unit == self.bufr_unit: print "Unit:", self.unit else: print "BUFR unit:", self.bufr_unit print "CREX unit:", self.unit if self.is_string(): print "Format: %d chars:" % self.len elif self.scale == 0: print "Format: %d digits" % self.len elif self.scale > 0: fmtdesc = "#" * min(self.len - self.scale, 99) fmtdesc += '.' fmtdesc += "#" * min(self.scale, 99) print "Format:", fmtdesc elif self.scale < 0: fmtdesc = "#" * min(self.len, 99) fmtdesc += "0" * min(-self.scale, 99) print "Format:", fmtdesc def is_string(self): "True if the variable is a string; false if it is a numeric value" return unit_is_string(self.unit) def check(self): "Consistency checks" if unit_is_string(self.bufr_unit) != unit_is_string(self.unit): return "CREX is_string (%s - %s) is different than BUFR is_string (%s - %s)" % ( self.unit, str(unit_is_string(self.unit)), self.bufr_unit, str(unit_is_string(self.bufr_unit))) return None # def irange(self): # "Range of int-converted values" # if self.is_string: # return 0, 0 # if self.len >= 10: # return -2**31, 2**31 # # def drange(self): # "Range of float, unconverted values" # if self.is_string: # return 0.0, 0.0 # # if (i->len >= 10) # { # i->imin = INT_MIN; # i->imax = INT_MAX; # } else { # /* # // We subtract 2 because 2^bit_len-1 is the # // BUFR missing value # int bufr_min = i->bit_ref; # int bufr_max = exp2(i->bit_len) + i->bit_ref - 2; # // We subtract 2 because 10^len-1 is the # // CREX missing value # int crex_min = -(int)(exp10(i->len) - 1.0); # int crex_max = (int)(exp10(i->len) - 2.0); # // Actually, we cannot subtract 2 because RADAR BUFR # // messages have 255 subsets, and the delayed # // replication field is 8 bits, so 255 is the missing # // value, and if we disallow it here we cannot import # // radars anymore. # */ # /* # * If the unit is the same between BUFR and CREX, take # * the most restrictive extremes. # * # * If the unit is different, take the most permissive # * extremes, to make sure to fit values in both units # */ # /* # if (strcmp(i->unit, i->bufr_unit) == 0) # { # i->imin = bufr_min > crex_min ? bufr_min : crex_min; # i->imax = bufr_max < crex_max ? bufr_max : crex_max; # } else { # i->imin = bufr_min < crex_min ? bufr_min : crex_min; # i->imax = bufr_max > crex_max ? bufr_max : crex_max; # } # */ # /* # i->imin = i->bit_ref; # i->imax = exp2(i->bit_len) + i->bit_ref - 2; # */ # i->imin = -(int)(exp10(i->len) - 1.0); # i->imax = (int)(exp10(i->len) - 1.0); # } # i->dmin = dba_var_decode_int(i->imin, i); # i->dmax = dba_var_decode_int(i->imax, i); def read_btable(fd): for idx, line in enumerate(fd): entry = Entry() entry.read_bufr(line) if len(line) >= 157: entry.read_crex(line[119:]) msg = entry.check() if msg is not None: print >>sys.stderr, "Line %d: %s" % (idx+1, msg) yield entry import readline class Completer(object): def __init__(self, func): self.func = func self.opts = [] def __call__(self, text, state): if state == 0: self.opts = list(self.func(text)) if state >= len(self.opts): return None return self.opts[state] class App(object): def __init__(self, tablefname): self.entries = list(read_btable(open(tablefname))) self.entry = None def get_entry(self, b): for e in self.entries: if e.var == b: return e return None def comp_field(self, text): for field in self.entry.FIELDS: if field.startswith(text): yield field def comp_val(self, text): res = set() for e in self.entries: val = str(getattr(e, self.field, "")) if val.startswith(text): res.add(val) return sorted(res) def main(self, var): readline.parse_and_bind("tab: complete") self.entry = self.get_entry(var) if self.entry is None: self.entry = Entry() self.entry.var = var while True: print "Current entry value:" self.entry.dump() readline.set_completer(Completer(self.comp_field)) self.field = raw_input("field to set (? for help, q to quit): ") if self.field == '?': print for f in self.entry.FIELDS: print "%s: %s" % (f, ENTRYDOC[f]) print continue elif self.field == 'q': break elif self.field == "": print continue elif self.field not in self.entry.FIELDS: print "Invalid field (try ? for help)." print continue else: readline.set_completer(Completer(self.comp_val)) print "%s: %s" % (self.field, ENTRYDOC[self.field]) print "current value:", getattr(self.entry, self.field) val = raw_input("value to set: ").strip() try: if self.field in self.entry.NUMFIELDS: val = int(val) setattr(self.entry, self.field, val) except Exception, e: print e print print self.entry.encode() app = App(sys.argv[1]) app.main(sys.argv[2]) dballe-7.7/src/Makefile.in0000644000175000017500000006151612652630066012406 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @FILE_OFFSET_BITS_64_TRUE@am__append_1 = -D_FILE_OFFSET_BITS=64 bin_PROGRAMS = dbatbl$(EXEEXT) dbamsg$(EXEEXT) dbadb$(EXEEXT) subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/m4_ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(dist_bin_SCRIPTS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_dbadb_OBJECTS = dbadb.$(OBJEXT) dbadb_OBJECTS = $(am_dbadb_OBJECTS) dbadb_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 = dbadb_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(dbadb_LDFLAGS) $(LDFLAGS) -o $@ am_dbamsg_OBJECTS = dbamsg.$(OBJEXT) dbamsg_OBJECTS = $(am_dbamsg_OBJECTS) dbamsg_LDADD = $(LDADD) dbamsg_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(dbamsg_LDFLAGS) $(LDFLAGS) -o $@ am_dbatbl_OBJECTS = dbatbl.$(OBJEXT) dbatbl_OBJECTS = $(am_dbatbl_OBJECTS) dbatbl_LDADD = $(LDADD) dbatbl_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(dbatbl_LDFLAGS) $(LDFLAGS) -o $@ am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } SCRIPTS = $(dist_bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(dbadb_SOURCES) $(dbamsg_SOURCES) $(dbatbl_SOURCES) DIST_SOURCES = $(dbadb_SOURCES) $(dbamsg_SOURCES) $(dbatbl_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FC = @FC@ FCFLAGS = @FCFLAGS@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDBALLEF_VERSION_INFO = @LIBDBALLEF_VERSION_INFO@ LIBDBALLE_VERSION_INFO = @LIBDBALLE_VERSION_INFO@ LIBOBJS = @LIBOBJS@ LIBPQ_CFLAGS = @LIBPQ_CFLAGS@ LIBPQ_LIBS = @LIBPQ_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ WREPORT_CFLAGS = @WREPORT_CFLAGS@ WREPORT_LIBS = @WREPORT_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_FC = @ac_ct_FC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_doxygen = @have_doxygen@ have_gperf = @have_gperf@ have_latex2html = @have_latex2html@ have_rst2html = @have_rst2html@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mysql_config = @mysql_config@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ tabledir = @tabledir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ DBALLELIBS = ../dballe/libdballe.la AM_CPPFLAGS = -I$(top_srcdir) $(WREPORT_CFLAGS) $(LUA_CFLAGS) \ $(am__append_1) dist_bin_SCRIPTS = dbatbl_makeb dbaexport dbatbl_SOURCES = dbatbl.cc dbatbl_LDFLAGS = $(DBALLELIBS) $(WREPORT_LIBS) -lpopt dbatbl_DEPENDENCIES = $(DBALLELIBS) dbamsg_SOURCES = dbamsg.cc dbamsg_LDFLAGS = $(DBALLELIBS) $(WREPORT_LIBS) -lpopt dbamsg_DEPENDENCIES = $(DBALLELIBS) dbadb_SOURCES = dbadb.cc dbadb_LDFLAGS = $(DBALLELIBS) $(WREPORT_LIBS) -lpopt dbadb_DEPENDENCIES = $(DBALLELIBS) all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *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);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_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 dbadb$(EXEEXT): $(dbadb_OBJECTS) $(dbadb_DEPENDENCIES) $(EXTRA_dbadb_DEPENDENCIES) @rm -f dbadb$(EXEEXT) $(AM_V_CXXLD)$(dbadb_LINK) $(dbadb_OBJECTS) $(dbadb_LDADD) $(LIBS) dbamsg$(EXEEXT): $(dbamsg_OBJECTS) $(dbamsg_DEPENDENCIES) $(EXTRA_dbamsg_DEPENDENCIES) @rm -f dbamsg$(EXEEXT) $(AM_V_CXXLD)$(dbamsg_LINK) $(dbamsg_OBJECTS) $(dbamsg_LDADD) $(LIBS) dbatbl$(EXEEXT): $(dbatbl_OBJECTS) $(dbatbl_DEPENDENCIES) $(EXTRA_dbatbl_DEPENDENCIES) @rm -f dbatbl$(EXEEXT) $(AM_V_CXXLD)$(dbatbl_LINK) $(dbatbl_OBJECTS) $(dbatbl_LDADD) $(LIBS) install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbadb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbamsg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbatbl.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-dist_binSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_binSCRIPTS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic 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-binPROGRAMS \ install-data install-data-am install-dist_binSCRIPTS \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-dist_binSCRIPTS .PRECIOUS: Makefile # 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: dballe-7.7/src/dbadb.cc0000644000175000017500000003342612652630043011676 00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace dballe; using namespace dballe::cmdline; using namespace wreport; using namespace std; // Command line parser variables struct cmdline::Reader reader; static const char* op_output_template = ""; const char* op_output_type = "bufr"; const char* op_report = ""; const char* op_dsn = ""; const char* op_user = ""; const char* op_pass = ""; int op_wipe_first = 0; int op_dump = 0; int op_overwrite = 0; int op_fast = 0; int op_no_attrs = 0; int op_full_pseudoana = 0; int op_verbose = 0; int op_precise_import = 0; struct poptOption grepTable[] = { { "category", 0, POPT_ARG_INT, &reader.filter.category, 0, "match messages with the given data category", "num" }, { "subcategory", 0, POPT_ARG_INT, &reader.filter.subcategory, 0, "match BUFR messages with the given data subcategory", "num" }, { "check-digit", 0, POPT_ARG_INT, &reader.filter.checkdigit, 0, "match CREX messages with check digit (if 1) or without check digit (if 0)", "num" }, { "parsable", 0, 0, &reader.filter.parsable, 0, "match only messages that can be parsed", 0 }, { "index", 0, POPT_ARG_STRING, &reader.filter.index, 0, "match messages with the index in the given range (ex.: 1-5,9,22-30)", "expr" }, POPT_TABLEEND }; struct poptOption dbTable[] = { { "dsn", 0, POPT_ARG_STRING, &op_dsn, 0, "DSN, or URL-like database definition, to use for connecting to the DB-All.e database (can also be specified in the environment as DBA_DB)", "dsn" }, { "user", 0, POPT_ARG_STRING, &op_user, 0, "username to use for connecting to the DB-All.e database", "user" }, { "pass", 0, POPT_ARG_STRING, &op_pass, 0, "password to use for connecting to the DB-All.e database", "pass" }, { "wipe-first", 0, POPT_ARG_NONE, &op_wipe_first, 0, "wipe database before any other action" }, POPT_TABLEEND }; static unique_ptr connect() { unique_ptr db; const char* chosen_dsn; /* If dsn is missing, look in the environment */ if (op_dsn[0] == 0) { chosen_dsn = getenv("DBA_DB"); if (chosen_dsn == NULL) throw error_consistency("no database specified"); } else chosen_dsn = op_dsn; /* If dsn looks like a url, treat it accordingly */ if (DB::is_url(chosen_dsn)) db = DB::connect_from_url(chosen_dsn); else db = DB::connect(chosen_dsn, op_user, op_pass); // Wipe database if requested if (op_wipe_first) db->reset(); return db; } // Command line parsing wrappers for Dbadb methods struct DatabaseCmd : public cmdline::Subcommand { void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back({ NULL, 0, POPT_ARG_INCLUDE_TABLE, &dbTable, 0, "Options used to connect to the database", 0 }); } }; struct DumpCmd : public DatabaseCmd { DumpCmd() { names.push_back("dump"); usage = "dump [options] [queryparm1=val1 [queryparm2=val2 [...]]]"; desc = "Dump data from the database"; longdesc = "Query parameters are the same of the Fortran API. " "Please see the section \"Input and output parameters -- For data " "related action routines\" of the Fortran API documentation for a " "complete list."; } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); /* Create the query */ core::Query query; dba_cmdline_get_query(optCon, query); unique_ptr db = connect(); Dbadb dbadb(*db); return dbadb.do_dump(query, stdout); } }; struct StationsCmd : public DatabaseCmd { StationsCmd() { names.push_back("stations"); usage = "stations [options] [queryparm1=val1 [queryparm2=val2 [...]]]"; desc = "List the stations present in the database"; longdesc = "Query parameters are the same of the Fortran API. " "Please see the section \"Input and output parameters -- For data " "related action routines\" of the Fortran API documentation for a " "complete list."; } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); /* Create the query */ core::Query query; dba_cmdline_get_query(optCon, query); unique_ptr db = connect(); Dbadb dbadb(*db); return dbadb.do_stations(query, stdout); } }; /// Create / empty the database struct WipeCmd : public DatabaseCmd { WipeCmd() { names.push_back("wipe"); usage = "wipe [options] [optional rep_memo description file]"; desc = "Reinitialise the database, removing all data"; longdesc = "Reinitialisation is done using the given report code description file. " "If no file is provided, a default version is used"; } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); /* Get the optional name of the repinfo file */ const char* fname = poptGetArg(optCon); { // Connect first using the current format, and remove all tables. unique_ptr db = connect(); db->disappear(); } // Recreate tables unique_ptr db = connect(); db->reset(fname); return 0; } }; /// Perform database cleanup maintenance struct CleanupCmd : public DatabaseCmd { CleanupCmd() { names.push_back("cleanup"); usage = "cleanup [options]"; desc = "Perform database cleanup operations"; longdesc = "The only operation currently performed by this command is " "deleting stations that have no values. If more will be added in " "the future, they will be documented here."; } int main(poptContext optCon) { unique_ptr db = connect(); db->vacuum(); return 0; } }; /// Update repinfo information in the database struct RepinfoCmd : public DatabaseCmd { RepinfoCmd() { names.push_back("repinfo"); usage = "repinfo [options] [filename]"; desc = "Update the report information table"; longdesc = "Update the report information table with the data from the given " "report code description file. " "If no file is provided, a default version is used"; } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); unique_ptr db = connect(); /* Get the optional name of the repinfo file. If missing, the default will be used */ const char* fname = poptGetArg(optCon); int added, deleted, updated; db->update_repinfo(fname, &added, &deleted, &updated); printf("Update completed: %d added, %d deleted, %d updated.\n", added, deleted, updated); return 0; } }; struct ImportCmd : public DatabaseCmd { ImportCmd() { names.push_back("import"); usage = "import [options] [filter] filename [filename [ ... ] ]"; desc = "Import data into the database"; } void add_to_optable(std::vector& opts) const override { DatabaseCmd::add_to_optable(opts); opts.push_back({ "type", 't', POPT_ARG_STRING, &reader.input_type, 0, "format of the input data ('bufr', 'crex', 'aof', 'csv', 'json')", "type" }); opts.push_back({ "rejected", 0, POPT_ARG_STRING, &reader.fail_file_name, 0, "write unprocessed data to this file", "fname" }); opts.push_back({ "overwrite", 'f', POPT_ARG_NONE, &op_overwrite, 0, "overwrite existing data", 0 }); opts.push_back({ "report", 'r', POPT_ARG_STRING, &op_report, 0, "force data to be of this type of report", "rep" }); opts.push_back({ "fast", 0, POPT_ARG_NONE, &op_fast, 0, "Prefer speed to transactional integrity: if the import is interrupted," " the database needs to be wiped and recreated.", 0 }); opts.push_back({ "no-attrs", 0, POPT_ARG_NONE, &op_no_attrs, 0, "do not import data attributes", 0 }); opts.push_back({ "full-pseudoana", 0, POPT_ARG_NONE, &op_full_pseudoana, 0, "merge pseudoana extra values with the ones already existing in the database", 0 }); opts.push_back({ "precise", 0, 0, &op_precise_import, 0, "import messages using precise contexts instead of standard ones", 0 }); opts.push_back({ NULL, 0, POPT_ARG_INCLUDE_TABLE, &grepTable, 0, "Options used to filter messages", 0 }); } int main(poptContext optCon) override { // Throw away the command name poptGetArg(optCon); // Configure the reader core::Query query; if (dba_cmdline_get_query(optCon, query) > 0) reader.filter.matcher_from_record(query); reader.import_opts.simplified = !op_precise_import; // Configure the importer int import_flags = 0; if (op_overwrite) import_flags |= DBA_IMPORT_OVERWRITE; if (op_fast) setenv("DBA_INSECURE_SQLITE", "true", true); if (!op_no_attrs) import_flags |= DBA_IMPORT_ATTRS; if (op_full_pseudoana) import_flags |= DBA_IMPORT_FULL_PSEUDOANA; unique_ptr db = connect(); const char* forced_repmemo = NULL; if (strcmp(op_report, "") != 0) forced_repmemo = op_report; Dbadb dbadb(*db); return dbadb.do_import(get_filenames(optCon), reader, import_flags, forced_repmemo); } }; struct ExportCmd : public DatabaseCmd { ExportCmd() { names.push_back("export"); usage = "export [options] rep_memo [queryparm1=val1 [queryparm2=val2 [...]]]"; desc = "Export data from the database"; longdesc = "Query parameters are the same of the Fortran API. " "Please see the section \"Input and output parameters -- For data " "related action routines\" of the Fortran API documentation for a " "complete list."; } void add_to_optable(std::vector& opts) const override { DatabaseCmd::add_to_optable(opts); opts.push_back({ "report", 'r', POPT_ARG_STRING, &op_report, 0, "force exported data to be of this type of report", "rep" }); opts.push_back({ "dest", 'd', POPT_ARG_STRING, &op_output_type, 0, "format of the data in output ('bufr', 'crex', 'aof')", "type" }); opts.push_back({ "template", 't', POPT_ARG_STRING, &op_output_template, 0, "template of the data in output (autoselect if not specified, 'list' gives a list)", "name" }); opts.push_back({ "dump", 0, POPT_ARG_NONE, &op_dump, 0, "dump data to be encoded instead of encoding it", 0 }); } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); if (strcmp(op_output_template, "list") == 0) { list_templates(); return 0; } // Reat the query from command line core::Query query; dba_cmdline_get_query(optCon, query); unique_ptr db = connect(); Dbadb dbadb(*db); const char* forced_repmemo = NULL; if (strcmp(op_report, "") != 0) forced_repmemo = op_report; if (op_dump) { return dbadb.do_export_dump(query, stdout); } else { File::Encoding type = File::parse_encoding(op_output_type); unique_ptr file = File::create(type, stdout, false, "w"); return dbadb.do_export(query, *file, op_output_template, forced_repmemo); } } }; struct DeleteCmd : public DatabaseCmd { DeleteCmd() { names.push_back("delete"); usage = "delete [options] [queryparm1=val1 [queryparm2=val2 [...]]]"; desc = "Delete all the data matching the given query parameters"; longdesc = "Query parameters are the same of the Fortran API. " "Please see the section \"Input and output parameters -- For data " "related action routines\" of the Fortran API documentation for a " "complete list."; } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); if (poptPeekArg(optCon) == NULL) dba_cmdline_error(optCon, "you need to specify some query parameters"); /* Add the query data from commandline */ core::Query query; dba_cmdline_get_query(optCon, query); unique_ptr db = connect(); // TODO: check that there is something db->remove(query); return 0; } }; int main (int argc, const char* argv[]) { Command dbadb; dbadb.name = "dbadb"; dbadb.desc = "Manage the DB-ALLe database"; dbadb.longdesc = "It allows to initialise the database, dump its contents and import and export data " "using BUFR, CREX or AOF encoding"; dbadb.add_subcommand(new DumpCmd); dbadb.add_subcommand(new StationsCmd); dbadb.add_subcommand(new WipeCmd); dbadb.add_subcommand(new CleanupCmd); dbadb.add_subcommand(new RepinfoCmd); dbadb.add_subcommand(new ImportCmd); dbadb.add_subcommand(new ExportCmd); dbadb.add_subcommand(new DeleteCmd); return dbadb.main(argc, argv); } /* vim:set ts=4 sw=4: */ dballe-7.7/src/Makefile.am0000644000175000017500000000124012652630043012354 00000000000000## Process this file with automake to produce Makefile.in DBALLELIBS = ../dballe/libdballe.la AM_CPPFLAGS = -I$(top_srcdir) $(WREPORT_CFLAGS) $(LUA_CFLAGS) if FILE_OFFSET_BITS_64 AM_CPPFLAGS += -D_FILE_OFFSET_BITS=64 endif bin_PROGRAMS = dbatbl dbamsg dist_bin_SCRIPTS = dbatbl_makeb dbaexport dbatbl_SOURCES = dbatbl.cc dbatbl_LDFLAGS = $(DBALLELIBS) $(WREPORT_LIBS) -lpopt dbatbl_DEPENDENCIES = $(DBALLELIBS) dbamsg_SOURCES = dbamsg.cc dbamsg_LDFLAGS = $(DBALLELIBS) $(WREPORT_LIBS) -lpopt dbamsg_DEPENDENCIES = $(DBALLELIBS) bin_PROGRAMS += dbadb dbadb_SOURCES = dbadb.cc dbadb_LDFLAGS = $(DBALLELIBS) $(WREPORT_LIBS) -lpopt dbadb_DEPENDENCIES = $(DBALLELIBS) dballe-7.7/src/dbaexport0000755000175000017500000001257012652630043012246 00000000000000#!/usr/bin/python # coding: utf-8 from __future__ import absolute_import from __future__ import print_function from __future__ import division from __future__ import unicode_literals import argparse import logging import os import sys import io try: import dballe HAS_DBALLE = True except ImportError: HAS_DBALLE = False log = logging.getLogger("main") class CommandError(Exception): pass def setup_logging(args): FORMAT = "%(levelname)s: %(message)s" if args.verbose: logging.basicConfig(level=logging.INFO, stream=sys.stderr, format=FORMAT) else: logging.basicConfig(level=logging.WARNING, stream=sys.stderr, format=FORMAT) def get_db(args): if not args.dsn: dsn = os.environ.get("DBA_DB", "") else: dsn = args.dsn if not dsn: raise CommandError("Cannot find a database to connect to: --dsn is not specified and $DBA_DB is not set") elif dballe.DB.is_url(dsn): return dballe.DB.connect_from_url(dsn) else: return dballe.DB.connect(dsn, args.user, args.password) def get_query(args): query = dballe.Record() for q in args.query: query.set_from_string(q) return query def get_outfd(args, text=False): """ Get the output file descriptor """ if args.outfile: if text: return io.open(args.outfile, "wt", encoding="utf-8") else: return io.open(args.outfile, "wb") else: if text: return io.open(sys.stdout.fileno(), "wt", encoding="utf-8", closefd=False) else: return io.open(sys.stdout.fileno(), "wb", closefd=False) if __name__ == "__main__": parser = argparse.ArgumentParser(description='Export data from a DB-All.e database.') parser.add_argument("--verbose", action="store_true", help="verbose output") parser.add_argument("--dsn", type=str, metavar="dsn", help="DSN, or URL-like database definition, to use for connecting to the DB-All.e database (can also be specified in the environment as DBA_DB)") parser.add_argument("--user", type=str, metavar="name", help="username to use for connecting to the DB-All.e database") parser.add_argument("--pass", type=str, metavar="password", dest="password", help="password to use for connecting to the DB-All.e database") parser.add_argument("--outfile", "-o", type=str, metavar="file", help="output file. Default is standard output, if supported") subparsers = parser.add_subparsers(dest="format", help="output formats") # Use a byte-string for subparser name to avoid seeing u'csv' in output. # Remove in python3 parser_csv = subparsers.add_parser(b"csv", help="export data as CSV") parser_csv.add_argument("query", nargs="*", metavar="key=val", help="DB-All.e query to select data to export") parser_gnur = subparsers.add_parser(b"gnur", help="export data as GNU R workspace") parser_gnur.add_argument("query", nargs="*", metavar="key=val", help="DB-All.e query to select data to export") parser_bufr = subparsers.add_parser(b"bufr", help="export data as BUFR") parser_bufr.add_argument("query", nargs="*", metavar="key=val", help="DB-All.e query to select data to export") parser_bufr.add_argument("--generic", action="store_true", help="export generic BUFR messages") parser_crex = subparsers.add_parser(b"crex", help="export data as CREX") parser_crex.add_argument("query", nargs="*", metavar="key=val", help="DB-All.e query to select data to export") parser_crex.add_argument("--generic", action="store_true", help="export generic BUFR messages") args = parser.parse_args() try: setup_logging(args) if not HAS_DBALLE: raise CommandError("This command requires the dballe python module to run") db = get_db(args) query = get_query(args) if args.format == "csv": import dballe.dbacsv with get_outfd(args, text=True) as fd: dballe.dbacsv.export(db, query, fd) elif args.format == "gnur": if not args.outfile: raise CommandError("cannot export R data to standard output: please use --outfile") import dballe.rconvert import dballe.volnd idx = (dballe.volnd.AnaIndex(), \ dballe.volnd.DateTimeIndex(), \ dballe.volnd.LevelIndex(), \ dballe.volnd.TimeRangeIndex(), \ dballe.volnd.NetworkIndex()) res = dballe.volnd.read(db.query_data(query), idx) dballe.rconvert.volnd_save_to_r(res, args.outfile) elif args.format == "bufr": if not args.outfile: raise CommandError("BUFR output requires --outfile") db.export_to_file(query, "BUFR", args.outfile, generic=args.generic) elif args.format == "crex": if not args.outfile: raise CommandError("CREX output requires --outfile") db.export_to_file(query, "CREX", args.outfile, generic=args.generic) else: raise CommandError("Exporter for {} is not available.".format(args.format)) except CommandError as e: log.error("%s", e) sys.exit(1) dballe-7.7/src/dbamsg.cc0000644000175000017500000012557612652630043012107 00000000000000/* For %zd */ #define _ISOC99_SOURCE #include "dballe/message.h" #include "dballe/msg/msg.h" #include "dballe/msg/context.h" #include "dballe/msg/aof_codec.h" #include "dballe/msg/bulletin.h" #include "dballe/record.h" #include "dballe/file.h" #include "dballe/core/query.h" #include "dballe/core/aoffile.h" #include "dballe/core/matcher.h" #include "dballe/core/csv.h" #include "dballe/core/json.h" #include "dballe/core/var.h" #include "dballe/cmdline/cmdline.h" #include "dballe/cmdline/processor.h" #include "dballe/cmdline/conversion.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace wreport; using namespace dballe; using namespace dballe::cmdline; using namespace std; static int op_dump_interpreted = 0; static int op_dump_text = 0; static int op_dump_csv = 0; static int op_dump_json = 0; static int op_dump_dds = 0; static int op_dump_structured = 0; static int op_precise_import = 0; static int op_bufr2netcdf_categories = 0; static const char* op_output_type = "bufr"; static const char* op_output_template = ""; static const char* op_output_file = "(stdout)"; static const char* op_report = ""; static const char* op_bisect_cmd = NULL; int op_verbose = 0; struct cmdline::Reader reader; struct poptOption grepTable[] = { { "category", 0, POPT_ARG_INT, &reader.filter.category, 0, "match messages with the given data category", "num" }, { "subcategory", 0, POPT_ARG_INT, &reader.filter.subcategory, 0, "match BUFR messages with the given data subcategory", "num" }, { "check-digit", 0, POPT_ARG_INT, &reader.filter.checkdigit, 0, "match CREX messages with check digit (if 1) or without check digit (if 0)", "num" }, { "unparsable", 0, 0, &reader.filter.unparsable, 0, "match only messages that cannot be parsed", 0 }, { "parsable", 0, 0, &reader.filter.parsable, 0, "match only messages that can be parsed", 0 }, { "index", 0, POPT_ARG_STRING, &reader.filter.index, 0, "match messages with the index in the given range (ex.: 1-5,9,22-30)", "expr" }, POPT_TABLEEND }; /// Write CSV output to the given output stream struct FileCSV : CSVWriter { FILE* out; FileCSV(FILE* out) : out(out) {} void flush_row() override { fputs(row.c_str(), out); putc('\n', out); row.clear(); } }; volatile int flag_bisect_stop = 0; void stop_bisect(int sig) { /* The signal handler just clears the flag and re-enables itself. */ flag_bisect_stop = 1; signal(sig, stop_bisect); } static int count_nonnulls(const Subset& raw) { unsigned i, count = 0; for (i = 0; i < raw.size(); i++) if (raw[i].isset()) count++; return count; } static void dump_common_header(const BinaryMessage& rmsg, const Bulletin& braw) { printf("Message %d\n", rmsg.index); printf("Size: %zd\n", rmsg.data.size()); printf("Master table number: %hhu\n", braw.master_table_number); printf("Origin: %hu:%hu\n", braw.originating_centre, braw.originating_subcentre); printf("Category: %hhu:%hhu:%hhu\n", braw.data_category, braw.data_subcategory, braw.data_subcategory_local); printf("Update sequence number: %hhu\n", braw.update_sequence_number); printf("Datetime: %04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu\n", braw.rep_year, braw.rep_month, braw.rep_day, braw.rep_hour, braw.rep_minute, braw.rep_second); printf("B Table: %s\n", braw.tables.btable ? braw.tables.btable->pathname().c_str() : "(none)"); printf("D Table: %s\n", braw.tables.dtable ? braw.tables.dtable->pathname().c_str() : "(none)"); } static void dump_bufr_header(const BinaryMessage& rmsg, const BufrBulletin& braw) { dump_common_header(rmsg, braw); printf("BUFR edition: %hhu\n", braw.edition_number); printf("Table version: %hhu:%hhu\n", braw.master_table_version_number, braw.master_table_version_number_local); printf("Compression: %s\n", braw.compression ? "yes" : "no"); printf("Optional section length: %zd\n", braw.optional_section.size()); printf("Subsets: %zd\n\n", braw.subsets.size()); } static void dump_crex_header(const BinaryMessage& rmsg, const CrexBulletin& braw) { dump_common_header(rmsg, braw); printf("CREX edition: %hhu\n", braw.edition_number); printf("Table version: %hhu/%hhu:%hhu\n", braw.master_table_version_number, braw.master_table_version_number_bufr, braw.master_table_version_number_local); printf("Check digit: %s\n\n", braw.has_check_digit ? "yes" : "no"); } static void dump_aof_header(const BinaryMessage& rmsg) { int category, subcategory; msg::AOFImporter::get_category(rmsg, &category, &subcategory); printf("Message %d\n", rmsg.index); printf("Size: %zd\n", rmsg.data.size()); printf("Category: %d:%d\n\n", category, subcategory); } static void print_bulletin_header(const Bulletin& braw) { printf(", origin %hu:%hu, category %hhu %hhu:%hhu:%hhu", braw.originating_centre, braw.originating_subcentre, braw.master_table_number, braw.data_category, braw.data_subcategory, braw.data_subcategory_local); } static void print_bufr_header(const BufrBulletin& braw) { print_bulletin_header(braw); printf(", bufr edition %hhu, tables %hhu:%hhu", braw.edition_number, braw.master_table_version_number, braw.master_table_version_number_local); printf(", subsets %zd, values:", braw.subsets.size()); for (size_t i = 0; i < braw.subsets.size(); ++i) printf(" %d/%zd", count_nonnulls(braw.subsets[i]), braw.subsets[i].size()); } static void print_crex_header(const CrexBulletin& braw) { print_bulletin_header(braw); printf(", crex edition %hhu, tables %hhu/%hhu:%hhu", braw.edition_number, braw.master_table_version_number, braw.master_table_version_number_bufr, braw.master_table_version_number_local); printf(", subsets %zd, values:", braw.subsets.size()); for (size_t i = 0; i < braw.subsets.size(); ++i) printf(" %d/%zd", count_nonnulls(braw.subsets[i]), braw.subsets[i].size()); } static void print_aof_header(const BinaryMessage& rmsg) { int category, subcategory; msg::AOFImporter::get_category(rmsg, &category, &subcategory); printf(", category %d, subcategory %d", category, subcategory); } static void print_item_header(const Item& item) { printf("#%d", item.idx); if (item.rmsg) { printf(" %s message: %zd bytes", File::encoding_name(item.rmsg->encoding), item.rmsg->data.size()); switch (item.rmsg->encoding) { case File::BUFR: if (item.bulletin != NULL) print_bufr_header(*dynamic_cast(item.bulletin)); break; case File::CREX: if (item.bulletin != NULL) print_crex_header(*dynamic_cast(item.bulletin)); break; case File::AOF: print_aof_header(*item.rmsg); break; } } else if (item.msgs) { printf(" message: %zd subsets:", item.msgs->size()); string old_type; unsigned count = 0; for (const auto& i: *item.msgs) { const Msg& m = Msg::downcast(i); string new_type = msg_type_name(m.type); if (old_type.empty()) { old_type = new_type; count = 1; } else if (old_type != new_type) { printf(" %u %s", count, old_type.c_str()); old_type = new_type; count = 1; } else ++count; } printf(" %u %s", count, old_type.c_str()); } } struct Summarise : public cmdline::Action { virtual bool operator()(const cmdline::Item& item) { print_item_header(item); puts("."); return true; } }; struct Head : public cmdline::Action { virtual bool operator()(const cmdline::Item& item) { if (!item.rmsg) return false; switch (item.rmsg->encoding) { case File::BUFR: if (item.bulletin == NULL) return true; dump_bufr_header(*item.rmsg, *dynamic_cast(item.bulletin)); puts("."); break; case File::CREX: if (item.bulletin == NULL) return true; dump_crex_header(*item.rmsg, *dynamic_cast(item.bulletin)); puts("."); break; case File::AOF: dump_aof_header(*item.rmsg); break; } return true; } }; static void dump_dba_vars(const Subset& msg) { for (size_t i = 0; i < msg.size(); ++i) msg[i].print(stdout); } /** * Print a bulletin in CSV format */ struct CSVBulletin : public cmdline::Action { msg::BulletinCSVWriter writer; CSVBulletin() : writer(stdout) {} virtual bool operator()(const cmdline::Item& item) { if (!item.rmsg) return false; if (!item.bulletin) return false; writer.output_bulletin(*item.bulletin); return true; } }; /** * Print a Msgs in CSV format */ struct CSVMsgs : public cmdline::Action { bool first; CSVMsgs() : first(true) {} virtual bool operator()(const cmdline::Item& item) { if (!item.msgs) return false; if (first) { Msg::csv_header(cout); first = false; } for (const auto& mi: *item.msgs) Msg::downcast(mi).to_csv(cout); return true; } }; /** * Print a Msgs in JSON format */ struct JSONMsgs : public cmdline::Action { core::JSONWriter json; JSONMsgs() : json(cout) {} ~JSONMsgs() { cout << flush; } virtual bool operator()(const cmdline::Item& item) { if (!item.msgs) return false; for (const auto& mi: *item.msgs) { const Msg& msg = Msg::downcast(mi); json.start_mapping(); json.add("version"); json.add(DBALLE_JSON_VERSION); json.add("network"); json.add(msg.get_rep_memo_var() ? msg.get_rep_memo_var()->enqc() : dballe::Msg::repmemo_from_type(msg.type)); json.add("ident"); if (msg.get_ident_var() != NULL) json.add(msg.get_ident_var()->enqc()); else json.add_null(); json.add("lon"); json.add_int(msg.get_longitude_var()->enqi()); json.add("lat"); json.add_int(msg.get_latitude_var()->enqi()); json.add("date"); std::stringstream ss; msg.get_datetime().to_stream_iso8601(ss, 'T', "Z"); json.add(ss.str().c_str()); json.add("data"); json.start_list(); for (const auto& ctx: msg.data) { json.start_mapping(); if (not ctx->is_station()) { json.add("timerange"); json.add(ctx->trange); json.add("level"); json.add(ctx->level); } json.add("vars"); json.start_mapping(); for (const auto& var: ctx->data) { json.add(wreport::varcode_format(var->code())); json.start_mapping(); json.add("v"); json.add(*var); json.add("a"); json.start_mapping(); for (const Var* attr = var->next_attr(); attr; attr = attr->next_attr()) { json.add(wreport::varcode_format(attr->code())); json.add(*attr); } json.end_mapping(); json.end_mapping(); } json.end_mapping(); json.end_mapping(); } json.end_list(); json.end_mapping(); json.add_break(); } return true; } }; struct DumpMessage : public cmdline::Action { void print_subsets(const Bulletin& braw) { for (size_t i = 0; i < braw.subsets.size(); ++i) { printf("Subset %zd:\n", i); dump_dba_vars(braw.subsets[i]); } } virtual bool operator()(const cmdline::Item& item) { print_item_header(item); if (!item.rmsg) { puts(": no low-level information available"); return true; } puts(":"); switch (item.rmsg->encoding) { case File::BUFR: { if (item.bulletin == NULL) return true; print_subsets(*item.bulletin); break; } case File::CREX: { if (item.bulletin == NULL) return true; print_subsets(*item.bulletin); break; } case File::AOF: msg::AOFImporter::dump(*item.rmsg, stdout); break; } return true; } }; struct DumpCooked : public cmdline::Action { virtual bool operator()(const cmdline::Item& item) { if (item.msgs == NULL) return false; for (size_t i = 0; i < item.msgs->size(); ++i) { printf("#%d[%zd] ", item.idx, i); (*item.msgs)[i].print(stdout); } return true; } }; static void print_var(const Var& var) { string formatted = var.format(""); printf("%01d%02d%03d %s\n", WR_VAR_FXY(var.code()), formatted.c_str()); } struct DumpText : public cmdline::Action { void add_keyval(const char* key, unsigned val) { printf("%s: %u\n", key, val); } void add_keyval(const char* key, const std::string& val) { printf("%s: %s\n", key, val.c_str()); } virtual bool operator()(const cmdline::Item& item) { if (item.bulletin == NULL) throw error_consistency("source is not a BUFR or CREX message"); const Bulletin& bul = *item.bulletin; add_keyval("master_table_number", bul.master_table_number); add_keyval("data_category", bul.data_category); add_keyval("data_subcategory", bul.data_subcategory); add_keyval("data_subcategory_local", bul.data_subcategory_local); add_keyval("originating_centre", bul.originating_centre); add_keyval("originating_subcentre", bul.originating_subcentre); add_keyval("update_sequence_number", bul.update_sequence_number); char buf[30]; snprintf(buf, 29, "%hu-%hhu-%hhu %hhu:%hhu:%hhu", bul.rep_year, bul.rep_month, bul.rep_day, bul.rep_hour, bul.rep_minute, bul.rep_second); add_keyval("representative_time", buf); if (const BufrBulletin* b = dynamic_cast(item.bulletin)) { add_keyval("encoding", "bufr"); add_keyval("edition_number", b->edition_number); add_keyval("master_table_version_number", b->master_table_version_number); add_keyval("master_table_version_number_local", b->master_table_version_number_local); add_keyval("compression", b->compression ? "true" : "false"); add_keyval("optional_section", b->optional_section); } else if (const CrexBulletin* b = dynamic_cast(item.bulletin)) { add_keyval("encoding", "crex"); add_keyval("edition_number", b->edition_number); add_keyval("master_table_version_number", b->master_table_version_number); add_keyval("master_table_version_number_bufr", b->master_table_version_number_bufr); add_keyval("master_table_version_number_local", b->master_table_version_number_local); add_keyval("has_check_digit", b->has_check_digit ? "true" : "false"); } else throw error_consistency("encoding not supported for CSV dump"); printf("descriptors:"); for (const auto& desc: bul.datadesc) printf(" %01d%02d%03d", WR_VAR_FXY(desc)); printf("\n"); for (size_t i = 0; i < bul.subsets.size(); ++i) { const Subset& subset = bul.subsets[i]; printf("subset %zd:\n", i + 1); for (size_t j = 0; j < subset.size(); ++j) { const Var& var = subset[j]; printf(" "); print_var(var); for (const Var* attr = var.next_attr(); attr; attr = attr->next_attr()) { printf(" *"); print_var(*attr); } } } return true; } }; struct DumpStructured : public cmdline::Action { virtual bool operator()(const cmdline::Item& item) { print_item_header(item); if (!item.rmsg) { puts(": no low-level information available"); return true; } if (!item.bulletin) { puts(": no bulletin information available"); return true; } puts(":"); item.bulletin->print_structured(stdout); return true; } }; struct DumpDDS : public cmdline::Action { virtual bool operator()(const cmdline::Item& item) { print_item_header(item); if (!item.rmsg) { puts(": no low-level information available"); return true; } if (!item.bulletin) { puts(": no bulletin information available"); return true; } puts(":"); item.bulletin->print_datadesc(stdout); return false; } }; struct WriteRaw : public cmdline::Action { File* file; WriteRaw() : file(0) {} ~WriteRaw() { if (file) delete file; } virtual bool operator()(const cmdline::Item& item) { if (!item.rmsg) return false; if (!file) file = File::create(item.rmsg->encoding, "(stdout)", "w").release(); file->write(item.rmsg->data); return true; } }; struct Scan : public cmdline::Subcommand { Scan() { names.push_back("scan"); usage = "scan [options] [filter] filename [filename [...]]"; desc = "Summarise the contents of a file with meteorological data"; } void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back({ "type", 't', POPT_ARG_STRING, &reader.input_type, 0, "format of the input data ('bufr', 'crex', 'aof')", "type" }); opts.push_back({ "rejected", 0, POPT_ARG_STRING, &reader.fail_file_name, 0, "write unprocessed data to this file", "fname" }); opts.push_back({ NULL, 0, POPT_ARG_INCLUDE_TABLE, &grepTable, 0, "Options used to filter messages", 0 }); } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); core::Query query; if (dba_cmdline_get_query(optCon, query) > 0) reader.filter.matcher_from_record(query); Summarise s; reader.read(get_filenames(optCon), s); return 0; } }; struct HeadCmd : public cmdline::Subcommand { HeadCmd() { names.push_back("head"); usage = "head [options] [filter] filename [filename [...]]"; desc = "Dump the contents of the header of a file with meteorological data"; } void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back({ "type", 't', POPT_ARG_STRING, &reader.input_type, 0, "format of the input data ('bufr', 'crex', 'aof')", "type" }); opts.push_back({ "rejected", 0, POPT_ARG_STRING, &reader.fail_file_name, 0, "write unprocessed data to this file", "fname" }); opts.push_back({ NULL, 0, POPT_ARG_INCLUDE_TABLE, &grepTable, 0, "Options used to filter messages", 0 }); } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); core::Query query; if (dba_cmdline_get_query(optCon, query) > 0) reader.filter.matcher_from_record(query); Head head; reader.read(get_filenames(optCon), head); return 0; } }; struct Dump : public cmdline::Subcommand { Dump() { names.push_back("dump"); usage = "dump [options] [filter] filename [filename [...]]"; desc = "Dump the contents of a file with meteorological data"; } void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back({ "type", 't', POPT_ARG_STRING, &reader.input_type, 0, "format of the input data ('bufr', 'crex', 'aof')", "type" }); opts.push_back({ "rejected", 0, POPT_ARG_STRING, &reader.fail_file_name, 0, "write unprocessed data to this file", "fname" }); opts.push_back({ "interpreted", 0, 0, &op_dump_interpreted, 0, "dump the message as understood by the importer", 0 }); opts.push_back({ "precise", 0, 0, &op_precise_import, 0, "import messages using precise contexts instead of standard ones", 0 }); opts.push_back({ "text", 0, 0, &op_dump_text, 0, "dump as text that can be processed by dbamsg makebufr", 0 }); opts.push_back({ "csv", 0, 0, &op_dump_csv, 0, "dump in machine readable CSV format", 0 }); opts.push_back({ "json", 0, 0, &op_dump_json, 0, "dump in machine readable JSON format", 0 }); opts.push_back({ "dds", 0, 0, &op_dump_dds, 0, "dump structure of data description section", 0 }); opts.push_back({ "structured", 0, 0, &op_dump_structured, 0, "structured dump of the message contents", 0 }); opts.push_back({ NULL, 0, POPT_ARG_INCLUDE_TABLE, &grepTable, 0, "Options used to filter messages", 0 }); } int main(poptContext optCon) override { unique_ptr action; if (op_dump_csv) { if (op_dump_interpreted) action.reset(new CSVMsgs); else action.reset(new CSVBulletin); } else if (op_dump_json) action.reset(new JSONMsgs); else if (op_dump_interpreted) action.reset(new DumpCooked); else if (op_dump_text) action.reset(new DumpText); else if (op_dump_structured) action.reset(new DumpStructured); else if (op_dump_dds) action.reset(new DumpDDS); else action.reset(new DumpMessage); /* Throw away the command name */ poptGetArg(optCon); if (op_precise_import) reader.import_opts.simplified = false; core::Query query; if (dba_cmdline_get_query(optCon, query) > 0) reader.filter.matcher_from_record(query); reader.read(get_filenames(optCon), *action); return 0; } }; struct Cat : public cmdline::Subcommand { Cat() { names.push_back("cat"); usage = "cat [options] [filter] filename [filename [...]]"; desc = "Dump the raw data of a file with meteorological data"; } void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back({ "type", 't', POPT_ARG_STRING, &reader.input_type, 0, "format of the input data ('bufr', 'crex', 'aof')", "type" }); opts.push_back({ "rejected", 0, POPT_ARG_STRING, &reader.fail_file_name, 0, "write unprocessed data to this file", "fname" }); opts.push_back({ NULL, 0, POPT_ARG_INCLUDE_TABLE, &grepTable, 0, "Options used to filter messages", 0 }); } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); core::Query query; if (dba_cmdline_get_query(optCon, query) > 0) reader.filter.matcher_from_record(query); /*DBA_RUN_OR_RETURN(aof_file_write_header(file, 0, 0)); */ WriteRaw wraw; reader.read(get_filenames(optCon), wraw); return 0; } }; struct StoreMessages : public cmdline::Action, public vector { virtual void operator()(const BinaryMessage& rmsg, const wreport::Bulletin*, const Messages*) { push_back(rmsg); } }; #if 0 static dba_err bisect_test(struct message_vector* vec, size_t first, size_t last, int* fails) { FILE* out = popen(op_bisect_cmd, "w"); int res; for (; first < last; ++first) { dba_rawmsg msg = vec->messages[first]; if (fwrite(msg->buf, msg->len, 1, out) == 0) return dba_error_system("writing message %d to test script", msg->index); } res = pclose(out); if (res == -1) return dba_error_system("running test script", first); *fails = (res != 0); return dba_error_ok(); } struct bisect_candidate { size_t first; size_t last; }; static dba_err bisect( struct bisect_candidate* cand, struct message_vector* vec, size_t first, size_t last) { int fails = 0; /* If we already narrowed it down to 1 messages, there is no need to test * further */ if (flag_bisect_stop || cand->last == cand->first + 1) return dba_error_ok(); if (op_verbose) fprintf(stderr, "Trying messages %zd-%zd (%zd selected, kill -HUP %d to stop)... ", first, last, cand->last - cand->first, getpid()); DBA_RUN_OR_RETURN(bisect_test(vec, first, last, &fails)); if (op_verbose) fprintf(stderr, fails ? "fail.\n" : "ok.\n"); if (fails) { size_t mid = (first + last) / 2; if (last-first < cand->last - cand->first) { cand->last = last; cand->first = first; } if (first < mid && mid != last) DBA_RUN_OR_RETURN(bisect(cand, vec, first, mid)); if (mid < last && mid != first) DBA_RUN_OR_RETURN(bisect(cand, vec, mid, last)); } return dba_error_ok(); } #endif struct Bisect : public cmdline::Subcommand { Bisect() { names.push_back("bisect"); usage = "bisect [options] --test=testscript filename"; desc = "Bisect filename and output the minimum subsequence found for which testscript fails."; longdesc = "Run testscript passing parts of filename on its stdin and checking the return code. Then divide the input in half and try on each half. Keep going until testscript does not fail in any portion of the file. Output to stdout the smallest portion for which testscript fails. This is useful to isolate the few messages in a file that cause problems"; } void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back({ "test", 0, POPT_ARG_STRING, &op_bisect_cmd, 0, "command to run to test a message group", "cmd" }); opts.push_back({ "type", 't', POPT_ARG_STRING, &reader.input_type, 0, "format of the input data ('bufr', 'crex', 'aof')", "type" }); opts.push_back({ "rejected", 0, POPT_ARG_STRING, &reader.fail_file_name, 0, "write unprocessed data to this file", "fname" }); opts.push_back({ NULL, 0, POPT_ARG_INCLUDE_TABLE, &grepTable, 0, "Options used to filter messages", 0 }); } int main(poptContext optCon) override { #if 0 struct message_vector vec = { 0, 0, 0 }; struct bisect_candidate candidate; int old_op_verbose = op_verbose; size_t i; /* Throw away the command name */ poptGetArg(optCon); if (op_bisect_cmd == NULL) return dba_error_consistency("you need to use --test=command"); /* Read all input messages a vector of dba_rawmsg */ op_verbose = 0; DBA_RUN_OR_RETURN(process_all(optCon, dba_cmdline_stringToMsgType(reader.input_type, optCon), &reader.filter, store_messages, &vec)); op_verbose = old_op_verbose; /* Establish a handler for SIGHUP signals. */ signal(SIGHUP, stop_bisect); /* Bisect working on the vector */ candidate.first = 0; candidate.last = vec.len; DBA_RUN_OR_RETURN(bisect(&candidate, &vec, candidate.first, candidate.last)); if (op_verbose) { if (flag_bisect_stop) fprintf(stderr, "Stopped by SIGHUP.\n"); fprintf(stderr, "Selected messages %zd-%zd.\n", candidate.first, candidate.last); } /* Output the candidate messages */ for (; candidate.first < candidate.last; ++candidate.first) { dba_rawmsg msg = vec.messages[candidate.first]; if (fwrite(msg->buf, msg->len, 1, stdout) == 0) return dba_error_system("writing message %d to standard output", msg->index); } for (i = 0; i < vec.len; ++i) dba_rawmsg_delete(vec.messages[i]); free(vec.messages); return dba_error_ok(); #endif throw error_unimplemented("bisect is currently not implemented"); } }; struct Convert : public cmdline::Subcommand { Convert() { names.push_back("convert"); names.push_back("conv"); usage = "convert [options] [filter] filename [filename [...]]"; desc = "Convert meteorological data between different formats"; } void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back({ "type", 't', POPT_ARG_STRING, &reader.input_type, 0, "format of the input data ('bufr', 'crex', 'aof', 'csv')", "type" }); opts.push_back({ "dest", 'd', POPT_ARG_STRING, &op_output_type, 0, "format of the data in output ('bufr', 'crex', 'aof')", "type" }); opts.push_back({ "rejected", 0, POPT_ARG_STRING, &reader.fail_file_name, 0, "write unprocessed data to this file", "fname" }); opts.push_back({ "template", 0, POPT_ARG_STRING, &op_output_template, 0, "template of the data in output (autoselect if not specified, 'list' gives a list)", "name" }); opts.push_back({ "report", 'r', POPT_ARG_STRING, &op_report, 0, "force output data to be of this type of report", "rep_memo" }); opts.push_back({ "precise", 0, 0, &op_precise_import, 0, "import messages using precise contexts instead of standard ones", 0 }); opts.push_back({ "bufr2netcdf-categories", 0, 0, &op_bufr2netcdf_categories, 0, "recompute data categories and subcategories according to message contents, for use as input to bufr2netcdf", 0 }); opts.push_back({ NULL, 0, POPT_ARG_INCLUDE_TABLE, &grepTable, 0, "Options used to filter messages", 0 }); opts.push_back({ "output", 'o', POPT_ARG_STRING, &op_output_file, 0, "destination file. Default: stdandard output", "fname" }); } int main(poptContext optCon) override { msg::Exporter::Options opts; cmdline::Converter conv; reader.verbose = op_verbose; /* Throw away the command name */ poptGetArg(optCon); if (strcmp(op_output_template, "list") == 0) { list_templates(); return 0; } core::Query query; if (dba_cmdline_get_query(optCon, query) > 0) reader.filter.matcher_from_record(query); if (op_precise_import) reader.import_opts.simplified = false; if (op_report[0] != 0) conv.dest_rep_memo = op_report; else conv.dest_rep_memo = NULL; if (op_output_template[0] != 0) { conv.dest_template = op_output_template; opts.template_name = op_output_template; } conv.bufr2netcdf_categories = op_bufr2netcdf_categories != 0; if (strcmp(op_output_type, "auto") == 0) conv.file = File::create(op_output_file, "w").release(); else conv.file = File::create(string_to_encoding(op_output_type), op_output_file, "w").release(); conv.exporter = msg::Exporter::create(conv.file->encoding(), opts).release(); reader.read(get_filenames(optCon), conv); return 0; } }; struct Compare : public cmdline::Subcommand { Compare() { names.push_back("compare"); names.push_back("cmp"); usage = "compare [options] filename1 [filename2]"; desc = "Compare two files with meteorological data"; } void add_to_optable(std::vector& opts) const override { Subcommand::add_to_optable(opts); opts.push_back({ "type1", 't', POPT_ARG_STRING, &reader.input_type, 0, "format of the first file to compare ('bufr', 'crex', 'aof')", "type" }); opts.push_back({ "type2", 'd', POPT_ARG_STRING, &op_output_type, 0, "format of the second file to compare ('bufr', 'crex', 'aof')", "type" }); opts.push_back({ "rejected", 0, POPT_ARG_STRING, &reader.fail_file_name, 0, "write unprocessed data to this file", "fname" }); opts.push_back({ NULL, 0, POPT_ARG_INCLUDE_TABLE, &grepTable, 0, "Options used to filter messages", 0 }); } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); /* Read the file names */ const char* file1_name = poptGetArg(optCon); if (file1_name == NULL) dba_cmdline_error(optCon, "input file needs to be specified"); const char* file2_name = poptGetArg(optCon); if (file2_name == NULL) file2_name = "(stdin)"; unique_ptr file1; unique_ptr file2; if (strcmp(reader.input_type, "auto") == 0) file1 = File::create(file1_name, "r"); else file1 = File::create(string_to_encoding(reader.input_type), file1_name, "r"); if (strcmp(op_output_type, "auto") == 0) file2 = File::create(file2_name, "r"); else file2 = File::create(string_to_encoding(op_output_type), file2_name, "r"); std::unique_ptr importer1 = msg::Importer::create(file1->encoding()); std::unique_ptr importer2 = msg::Importer::create(file2->encoding()); size_t idx = 0; for ( ; ; ++idx) { ++idx; BinaryMessage msg1 = file1->read(); BinaryMessage msg2 = file2->read(); bool found1 = msg1; bool found2 = msg2; if (found1 != found2) throw error_consistency("The files contain a different number of messages"); if (!found1 && !found2) break; Messages msgs1 = importer1->from_binary(msg1); Messages msgs2 = importer2->from_binary(msg2); notes::Collect c(cerr); int diffs = msgs1.diff(msgs2); if (diffs > 0) error_consistency::throwf("Messages #%zd contain %d differences", idx, diffs); } if (idx == 0) throw error_consistency("The files do not contain messages"); return 0; } }; struct FixAOF : public cmdline::Subcommand { FixAOF() { names.push_back("fixaof"); usage = "fixaof [options] filename [filename1 [...]]]"; desc = "Recomputes the start and end of observation period in the headers of the given AOF files"; } int main(poptContext optCon) override { /* Throw away the command name */ poptGetArg(optCon); int count = 0; while (const char* filename = poptGetArg(optCon)) { unique_ptr file = File::create(File::AOF, filename, "rb+"); core::AofFile* aoffile = dynamic_cast(file.get()); aoffile->fix_header(); ++count; } if (count == 0) dba_cmdline_error(optCon, "at least one input file needs to be specified"); return 0; } }; #if 0 static dba_err readfield(FILE* in, char** name, char** value) { static char line[1000]; char* s; if (fgets(line, 1000, in) == NULL) { *name = *value = NULL; return dba_error_ok(); } s = strchr(line, ':'); if (s == NULL) { *name = NULL; *value = line; } else { *s = 0; *name = line; *value = s + 1; } if (*value) { int len; /* Trim value */ while (**value && isspace(**value)) ++*value; len = strlen(*value); while (len > 0 && isspace((*value)[len-1])) { --len; (*value)[len] = 0; } } return dba_error_ok(); } #endif #if 0 static dba_err parsetextgrib(FILE* in, bufrex_msg msg, int* found) { dba_err err = DBA_OK; bufrex_subset subset = NULL; char* name; char* value; dba_var var = NULL; *found = 0; bufrex_msg_reset(msg); while (1) { DBA_RUN_OR_GOTO(cleanup, readfield(in, &name, &value)); /* fprintf(stderr, "GOT NAME %s VALUE \"%s\"\n", name, value); */ if (name != NULL) { if (strcasecmp(name, "edition") == 0) { msg->edition = strtoul(value, 0, 10); } else if (strcasecmp(name, "type") == 0) { msg->type = strtoul(value, 0, 10); } else if (strcasecmp(name, "subtype") == 0) { msg->subtype = strtoul(value, 0, 10); } else if (strcasecmp(name, "localsubtype") == 0) { msg->localsubtype = strtoul(value, 0, 10); } else if (strcasecmp(name, "centre") == 0) { msg->opt.bufr.centre = strtoul(value, 0, 10); } else if (strcasecmp(name, "subcentre") == 0) { msg->opt.bufr.subcentre = strtoul(value, 0, 10); } else if (strcasecmp(name, "mastertable") == 0) { msg->opt.bufr.master_table = strtoul(value, 0, 10); } else if (strcasecmp(name, "localtable") == 0) { msg->opt.bufr.local_table = strtoul(value, 0, 10); } else if (strcasecmp(name, "compression") == 0) { msg->opt.bufr.compression = strtoul(value, 0, 10); } else if (strcasecmp(name, "reftime") == 0) { if (sscanf(value, "%04d-%02d-%02d %02d:%02d:%02d", &msg->rep_year, &msg->rep_month, &msg->rep_day, &msg->rep_hour, &msg->rep_minute, &msg->rep_second) != 6) return dba_error_consistency("Reference time \"%s\" cannot be parsed", value); } else if (strcasecmp(name, "descriptors") == 0) { const char* s = value; DBA_RUN_OR_GOTO(cleanup, bufrex_msg_load_tables(msg)); while (1) { size_t size = strcspn(s, " \t"); s += size; size = strspn(s, "BCDR0123456789"); if (size == 0) break; else DBA_RUN_OR_GOTO(cleanup, bufrex_msg_append_datadesc(msg, dba_descriptor_code(s))); } } else if (strcasecmp(name, "data") == 0) { /* Start a new subset */ DBA_RUN_OR_GOTO(cleanup, bufrex_msg_get_subset(msg, msg->subsets_count, &subset)); *found = 1; } } else if (value != NULL) { dba_varinfo info; int isattr = 0; dba_varcode code; if (value[0] == 0) /* End of one message */ break; /* Read a Bsomething (value or attribute) and append it to the subset */ if (value[0] == '*') { isattr = 1; ++value; } code = dba_descriptor_code(value); DBA_RUN_OR_GOTO(cleanup, bufrex_msg_query_btable(msg, code, &info)); while (*value && !isspace(*value)) ++value; while (*value && isspace(*value)) ++value; if (*value == 0) { /* Undef */ DBA_RUN_OR_GOTO(cleanup, dba_var_create(info, &var)); } else { if (VARINFO_IS_STRING(info)) { DBA_RUN_OR_GOTO(cleanup, dba_var_createc(info, value, &var)); } else { DBA_RUN_OR_GOTO(cleanup, dba_var_created(info, strtod(value, NULL), &var)); } } if (isattr) { DBA_RUN_OR_GOTO(cleanup, bufrex_subset_add_attr(subset, var)); dba_var_delete(var); } else { DBA_RUN_OR_GOTO(cleanup, bufrex_subset_store_variable(subset, var)); } var = NULL; } else { /* End of input */ break; } } cleanup: if (var) dba_var_delete(var); return err == DBA_OK ? dba_error_ok() : err; } #endif struct MakeBUFR : public cmdline::Subcommand { MakeBUFR() { names.push_back("makebufr"); names.push_back("mkbufr"); usage = "makebufr [options] filename [filename1 [...]]]"; desc = "Read a simple description of a BUFR file and output the BUFR file."; longdesc = "Read a simple description of a BUFR file and output the BUFR file. This only works for simple BUFR messages without attributes encoded with data present bitmaps"; } int main(poptContext optCon) override { throw error_unimplemented("makebufr not implemented"); #if 0 dba_err err = DBA_OK; bufrex_msg msg = NULL; dba_rawmsg rmsg = NULL; dba_file outfile = NULL; const char* filename; FILE* in = NULL; int count = 0; DBA_RUN_OR_RETURN(bufrex_msg_create(BUFREX_BUFR, &msg)); DBA_RUN_OR_GOTO(cleanup, dba_file_create(BUFR, "(stdout)", "w", &outfile)); /* Throw away the command name */ poptGetArg(optCon); while ((filename = poptGetArg(optCon)) != NULL) { int found; in = fopen(filename, "r"); if (in == NULL) { err = dba_error_system("opening file %s", filename); goto cleanup; } while (1) { DBA_RUN_OR_GOTO(cleanup, parsetextgrib(in, msg, &found)); if (found) { DBA_RUN_OR_GOTO(cleanup, bufrex_msg_encode(msg, &rmsg)); DBA_RUN_OR_GOTO(cleanup, dba_file_write(outfile, rmsg)); dba_rawmsg_delete(rmsg); rmsg = NULL; } else break; } fclose(in); in = NULL; ++count; } if (count == 0) dba_cmdline_error(optCon, "at least one input file needs to be specified"); cleanup: if (in != NULL) fclose(in); if (msg) bufrex_msg_delete(msg); if (rmsg) dba_rawmsg_delete(rmsg); if (outfile) dba_file_delete(outfile); return err == DBA_OK ? dba_error_ok() : err; #endif return 0; } }; int main (int argc, const char* argv[]) { Command dbamsg; dbamsg.name = "dbamsg"; dbamsg.desc = "Work with encoded meteorological data"; dbamsg.longdesc = "Examine, dump and convert files containing meteorological data. " "It supports observations encoded in BUFR, CREX and AOF formats"; dbamsg.manpage_examples_section = R"( Here are some example invocations of \\fBdbamsg\\fP: .P .nf # Convert an AOF message to BUFR dbamsg convert file.aof > file.bufr # Convert a BUFR message to CREX dbamsg convert file.bufr -d crex > file.crex # Convert BUFR messages to CREX, but skip all those not in january 2010 dbamsg convert year=2010 month=1 file.bufr -d crex > file.crex # Dump the content of a message, as they are in the message dbamsg dump file.bufr # Dump the content of a message, interpreted as physical quantities dbamsg dump --interpreted file.bufr .fi )"; dbamsg.add_subcommand(new Scan); dbamsg.add_subcommand(new HeadCmd); dbamsg.add_subcommand(new Dump); dbamsg.add_subcommand(new Cat); dbamsg.add_subcommand(new Bisect); dbamsg.add_subcommand(new Convert); dbamsg.add_subcommand(new Compare); dbamsg.add_subcommand(new FixAOF); dbamsg.add_subcommand(new MakeBUFR); return dbamsg.main(argc, argv); } dballe-7.7/LICENSE0000644000175000017500000004321412652630043010545 00000000000000Copyright (C) 2005--2015 ARPA-SIM License: GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. dballe-7.7/config.h.in0000644000175000017500000000500612652630065011564 00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* define if the compiler supports basic C++11 syntax */ #undef HAVE_CXX11 /* Have Fortran bindings */ #undef HAVE_DBALLEF /* Have Python bindings */ #undef HAVE_DBALLE_PYTHON /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* PostgreSQL is available */ #undef HAVE_LIBPQ /* lua is available */ #undef HAVE_LUA /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* MySQL is available */ #undef HAVE_MYSQL /* Have DB module */ #undef HAVE_ODBC /* sql.h (part of unixodbc) has been found */ #undef HAVE_ODBC_H /* popt.h has been found */ #undef HAVE_POPT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* we can use strcasestr */ #undef HAVE_STRCASESTR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* we need to use our own bswap_* functions */ #undef USE_OWN_BSWAP /* we need to use our own vasprintf */ #undef USE_OWN_VASPRINTF /* Version number of package */ #undef VERSION /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES dballe-7.7/compile0000755000175000017500000001624512652630066011127 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: dballe-7.7/m4/0000755000175000017500000000000012653425047010143 500000000000000dballe-7.7/m4/ax_append_flag.m40000644000175000017500000000530412652630043013250 00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_append_flag.html # =========================================================================== # # SYNOPSIS # # AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) # # DESCRIPTION # # FLAG is appended to the FLAGS-VARIABLE shell variable, with a space # added in between. # # If FLAGS-VARIABLE is not specified, the current language's flags (e.g. # CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains # FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly # FLAG. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 2 AC_DEFUN([AX_APPEND_FLAG], [AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl AS_VAR_SET_IF(FLAGS, [case " AS_VAR_GET(FLAGS) " in *" $1 "*) AC_RUN_LOG([: FLAGS already contains $1]) ;; *) AC_RUN_LOG([: FLAGS="$FLAGS $1"]) AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) ;; esac], [AS_VAR_SET(FLAGS,["$1"])]) AS_VAR_POPDEF([FLAGS])dnl ])dnl AX_APPEND_FLAG dballe-7.7/m4/m4_ax_cxx_compile_stdcxx_11.m40000644000175000017500000001073312652630043015622 00000000000000# ============================================================================ # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html # ============================================================================ # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the C++11 # standard; if necessary, add switches to CXXFLAGS to enable support. # # The first argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for an extended mode. # # The second argument, if specified 'mandatory' or if left unspecified, # indicates that baseline C++11 support is required and that the macro # should error out if no mode with that support is found. If specified # 'optional', then configuration proceeds regardless, after defining # HAVE_CXX11 if and only if a supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 3 m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [ template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; typedef check> right_angle_brackets; int a; decltype(a) b; typedef check check_type; check_type c; check_type&& cr = static_cast(c); auto d = a; ]) AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl m4_if([$1], [], [], [$1], [ext], [], [$1], [noext], [], [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], [$2], [optional], [ax_cxx_compile_cxx11_required=false], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl AC_LANG_PUSH([C++])dnl ac_success=no AC_CACHE_CHECK(whether $CXX supports C++11 features by default, ax_cv_cxx_compile_cxx11, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], [ax_cv_cxx_compile_cxx11=yes], [ax_cv_cxx_compile_cxx11=no])]) if test x$ax_cv_cxx_compile_cxx11 = xyes; then ac_success=yes fi m4_if([$1], [noext], [], [dnl if test x$ac_success = xno; then for switch in -std=gnu++11; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, $cachevar, [ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], [eval $cachevar=yes], [eval $cachevar=no]) CXXFLAGS="$ac_save_CXXFLAGS"]) if eval test x\$$cachevar = xyes; then CXXFLAGS="$CXXFLAGS $switch" ac_success=yes break fi done fi]) m4_if([$1], [ext], [], [dnl if test x$ac_success = xno; then for switch in -std=c++11; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, $cachevar, [ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], [eval $cachevar=yes], [eval $cachevar=no]) CXXFLAGS="$ac_save_CXXFLAGS"]) if eval test x\$$cachevar = xyes; then CXXFLAGS="$CXXFLAGS $switch" ac_success=yes break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx11_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) fi else if test x$ac_success = xno; then HAVE_CXX11=0 AC_MSG_NOTICE([No compiler with C++11 support was found]) else HAVE_CXX11=1 AC_DEFINE(HAVE_CXX11,1, [define if the compiler supports basic C++11 syntax]) fi AC_SUBST(HAVE_CXX11) fi ]) dballe-7.7/m4/lt~obsolete.m40000644000175000017500000001375612652630056012710 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) dballe-7.7/m4/pkg.m40000644000175000017500000001214512652630043011102 00000000000000# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # # Similar to PKG_CHECK_MODULES, make sure that the first instance of # this or PKG_CHECK_MODULES is called, or make sure to call # PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_ifval([$2], [$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$PKG_CONFIG"; then if test -n "$$1"; then pkg_cv_[]$1="$$1" else PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], [pkg_failed=yes]) fi else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` else $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD ifelse([$4], , [AC_MSG_ERROR(dnl [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT ])], [AC_MSG_RESULT([no]) $4]) elif test $pkg_failed = untried; then ifelse([$4], , [AC_MSG_FAILURE(dnl [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) ifelse([$3], , :, [$3]) fi[]dnl ])# PKG_CHECK_MODULES dballe-7.7/m4/ltversion.m40000644000175000017500000000126212652630055012347 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # 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. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) dballe-7.7/m4/libtool.m40000644000175000017500000106011112652630055011765 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # 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. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $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. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # 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"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # 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"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # 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"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # 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 $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # 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 -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # 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 -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; 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 "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # 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"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # 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"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # 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"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS dballe-7.7/m4/ltoptions.m40000644000175000017500000003007312652630055012357 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) dballe-7.7/m4/python.m40000644000175000017500000002157212652630043011646 00000000000000## ------------------------ -*- Autoconf -*- ## Python file handling ## From Andrew Dalke ## Updated by James Henstridge ## ------------------------ # Copyright (C) 1999-2013 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_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ 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]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Getting [:3] seems to be dnl the best way to do this; it's what "site.py" does in the standard dnl library. AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made dnl distinct variables so they can be overridden if need be. However, dnl general consensus is that you shouldn't need this ability. AC_SUBST([PYTHON_PREFIX], ['${prefix}']) AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) dnl At times (like when building shared libraries) you may want dnl to know which OS platform Python thinks this is. AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl Set up 4 directories: dnl pythondir -- where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON script directory], [am_cv_python_pythondir], [if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl pkgpythondir -- $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl pyexecdir -- directory for installing python extension modules dnl (shared libraries) dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], [am_cv_python_pyexecdir], [if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) dballe-7.7/m4/ltsugar.m40000644000175000017500000001042412652630055012003 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) dballe-7.7/m4/ax_cflags_warn_all.m40000644000175000017500000001163412652630043014131 00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html # =========================================================================== # # SYNOPSIS # # AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] # AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] # AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] # # DESCRIPTION # # Try to find a compiler option that enables most reasonable warnings. # # For the GNU compiler it will be -Wall (and -ansi -pedantic) The result # is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default. # # Currently this macro knows about the GCC, Solaris, Digital Unix, AIX, # HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and # Intel compilers. For a given compiler, the Fortran flags are much more # experimental than their C equivalents. # # - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS # - $2 add-value-if-not-found : nothing # - $3 action-if-found : add value to shellvariable # - $4 action-if-not-found : nothing # # NOTE: These macros depend on AX_APPEND_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2010 Rhys Ulerich # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 13 AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings], VAR,[VAR="no, unknown" ac_save_[]FLAGS="$[]FLAGS" for ac_arg dnl in "-warn all % -warn all" dnl Intel "-pedantic % -Wall" dnl GCC "-xstrconst % -v" dnl Solaris C "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX "-ansi -ansiE % -fullwarn" dnl IRIX "+ESlit % +w1" dnl HP-UX C "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10) "-h conform % -h msglevel 2" dnl Cray C (Unicos) # do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) done FLAGS="$ac_save_[]FLAGS" ]) AS_VAR_POPDEF([FLAGS])dnl case ".$VAR" in .ok|.ok,*) m4_ifvaln($3,$3) ;; .|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;; *) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;; esac AS_VAR_POPDEF([VAR])dnl ])dnl AX_FLAGS_WARN_ALL dnl implementation tactics: dnl the for-argument contains a list of options. The first part of dnl these does only exist to detect the compiler - usually it is dnl a global option to enable -ansi or -extrawarnings. All other dnl compilers will fail about it. That was needed since a lot of dnl compilers will give false positives for some option-syntax dnl like -Woption or -Xoption as they think of it is a pass-through dnl to later compile stages or something. The "%" is used as a dnl delimiter. A non-option comment can be given after "%%" marks dnl which will be shown but not added to the respective C/CXXFLAGS. AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl AC_LANG_PUSH([C]) AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) AC_LANG_POP([C]) ]) AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl AC_LANG_PUSH([C++]) AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) AC_LANG_POP([C++]) ]) AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl AC_LANG_PUSH([Fortran]) AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) AC_LANG_POP([Fortran]) ]) dballe-7.7/extra/0000755000175000017500000000000012653425051010741 500000000000000dballe-7.7/extra/test-crex-d-table.txt0000644000175000017500000052523112652630043014654 00000000000000 D00002 2 B00002 B00003 D00003 3 B00010 B00011 B00012 D00004 9 D00003 B00013 B00014 B00015 B00016 B00017 B00018 B00019 B00020 D00010 3 D00003 R01000 B00030 D01001 2 B01001 B01002 D01002 3 B01003 B01004 B01005 D01003 3 B01011 B01012 B01013 D01004 4 B01001 B01002 B01015 B02001 D01011 3 B04001 B04002 B04003 D01012 2 B04004 B04005 D01013 3 B04004 B04005 B04006 D01021 2 B05001 B06001 D01022 3 B05001 B06001 B07001 D01023 2 B05002 B06002 D01024 3 B05002 B06002 B07001 D01025 3 D01023 B04003 D01012 D01026 7 D01021 B04003 B04003 B04004 B04004 B04005 B04005 D01029 3 B01018 B02001 D01011 D01030 4 B01018 B02001 D01011 D01024 D01031 5 D01001 B02001 D01011 D01012 D01022 D01032 5 D01001 B02001 D01011 D01012 D01024 D01033 5 B01005 B02001 D01011 D01012 D01021 D01034 5 B01005 B02001 D01011 D01012 D01023 D01035 7 B01005 B01012 B01013 B02001 D01011 D01012 D01023 D01036 5 D01003 B02001 D01011 D01012 D01023 D01037 6 D01001 B02011 B02012 D01011 D01012 D01022 D01038 6 D01001 B02011 B02012 D01011 D01012 D01024 D01039 6 D01003 B02011 B02012 D01011 D01012 D01023 D01040 6 D01003 B02011 B02012 D01011 D01012 D01024 D01041 5 B01007 B02021 B02022 D01011 D01012 D01042 2 D01041 D01021 D01043 5 B01007 B02023 D01011 D01013 D01021 D01044 5 B01007 B02024 D01011 D01013 D01021 D01049 5 B02111 B02112 B21062 B21063 B21065 D01051 6 B01006 B02061 D01011 D01012 D01021 B08004 D01055 7 B01005 B02001 D01011 D01012 D01021 B01012 B01014 D01062 2 R01000 D01001 D01065 8 B01006 B01008 B02001 B02002 B02005 B02062 B02070 B02065 D01066 6 D01011 D01013 D01023 B07004 B02064 B08004 D01070 3 B02143 B02142 B02144 D01071 5 B01007 B01031 B02020 B02028 B02029 D01072 4 D01071 D01011 D01013 D01021 D01074 4 B02143 B02142 B02145 B02146 D01075 6 D01001 B01015 D01024 B08021 D01011 D01012 D01076 3 B02011 B02143 B02142 D01090 6 D01004 D01011 D01012 D01021 B07030 B07031 D01091 10 B02180 B02181 B02182 B02183 B02184 B02179 B02186 B02187 B02188 B02189 D01193 5 001007 001031 002196 002221 002222 D01250 4 D01193 D01011 D01013 D01021 D02001 4 B10004 B10051 B10061 B10063 D02002 5 B10004 B07004 B10003 B10061 B10063 D02003 9 B11011 B11012 B12004 B12006 B13003 B20001 B20003 B20004 B20005 D02004 7 B20010 B08002 B20011 B20013 B20012 B20012 B20012 D02005 4 B08002 B20011 B20012 B20013 D02006 4 B10004 B10051 B10062 B10063 D02011 3 D02001 D02003 D02004 D02012 3 D02002 D02003 D02004 D02013 4 D02006 D02003 R01000 D02005 D02021 3 B22001 B22011 B22021 D02022 3 B22002 B22012 B22022 D02023 3 B22003 B22013 B22023 D02024 3 D02022 R01002 D02023 D02051 12 B10004 B10051 B07004 B10003 B12004 B12051 B12016 B12017 B13004 R02004 B08051 B08020 D02069 4 B07032 B07033 B33041 B20001 D02070 8 B07032 B07033 B11001 B11002 B11043 B11041 B11016 B11017 D02071 14 B07032 B07033 B08021 B04025 B11001 B11002 B08021 R03002 B04025 B11043 B11041 B04025 B11016 B11017 D02072 5 B07032 B07033 B12101 B12103 B13003 D02073 7 B20010 R05004 B08002 B20011 B20012 B33041 B20013 D02074 4 B20003 B04025 B20004 B20005 D02075 5 B08021 B04025 B13055 B13058 B08021 D02076 7 B02021 B20022 B26020 B20023 B20024 B20025 B20026 D02077 12 B07032 B07033 B04025 B12111 B12112 B07032 B04025 B12112 B02176 B20062 B02177 B13013 D02078 4 B02176 B20062 B02177 B13013 D02079 5 B07032 B02175 B02178 B04025 B13011 D02080 3 B02185 B04025 B13033 D02081 2 B04025 B14031 D02082 7 B04025 B14002 B14004 B14016 B14028 B14029 B14030 D02083 8 B04025 B08023 B10004 B11001 B11002 B12101 B13003 B08023 D03001 3 B07003 B11001 B11002 D03002 3 B07004 B11001 B11002 D03003 4 B07004 B10003 B12001 B12003 D03004 6 B07004 B10003 B12001 B12003 B11001 B11002 D03011 4 B07003 B08001 B11001 B11002 D03012 4 B07004 B08001 B11001 B11002 D03013 7 B07004 B08001 B10003 B12001 B13003 B11001 B11002 D03014 7 B07004 B08001 B10003 B12001 B12003 B11001 B11002 D03031 6 B07004 B08003 B07021 B07022 B08012 B12061 D03032 2 B20011 B20016 D03033 2 B20010 B20016 D03041 8 B02152 B02023 B07004 B11001 B11002 B02153 B02154 B12071 D03250 8 B02252 B02023 B07004 B11001 B11002 B02197 B02198 B12193 D04001 5 B08003 B10004 B12001 B11001 B11002 D04002 4 B08003 B10004 B11001 B11002 D04003 2 B08003 B12001 D04004 4 B08003 B10004 B20010 B12001 D04005 4 B02024 B07004 B07004 B13003 D04006 3 B14001 B14001 B14003 D04011 27 B02163 B02164 B08012 B07024 B02057 B08021 B04001 B04002 B04003 B04004 B08021 B04024 R10004 B08021 B04004 B04005 B04006 B08021 B04004 B04005 B04006 B11001 B11002 R03010 B02163 B07004 B12001 D04030 3 B27031 B28031 B10031 D04031 3 B01041 B01042 B01043 D04032 5 B02153 B02154 B20081 B20082 B20012 D04033 8 B02152 B02166 B02167 B02153 B02154 B12075 B12076 B12063 D04034 9 R02004 B27001 B28001 B07022 B05043 B20010 B20016 B33003 B10040 D04250 27 B02231 B02232 B08012 B07024 B02057 B08021 B04001 B04002 B04003 B04004 B08021 B04024 R10004 B08021 B04004 B04005 B04006 B08021 B04004 B04005 B04006 B11001 B11002 R03010 B02231 B07004 B12001 D05001 4 B11001 B11002 B13060 B13071 D05002 11 D01012 B12001 B13003 B14051 B13060 B13072 B13080 B13081 B13082 B13083 B13084 D05003 4 D01012 B04065 R01000 D05001 D05004 3 D01030 D05002 D05003 D05006 8 B13072 B13082 B13019 C07005 C01004 B12001 B13073 B13060 D05007 5 D01029 D01012 B04065 R01000 D05006 D05008 4 D05006 C07005 C01004 B12030 D05009 5 D01029 D01012 B04065 R01000 D05008 D05010 3 D05008 B02091 B02091 D05011 5 D01029 D01012 B04065 R01000 D05010 D05016 7 B14021 B07004 B13003 B11002 B11001 B11041 B11043 D05017 5 B13080 B13081 B13083 B13085 B13084 D05018 7 D01029 D01012 B04065 R03000 D05008 D05016 D05017 D06001 4 B02032 R02000 B07062 B22042 D06002 3 B02031 B22004 B22031 D06003 4 B02002 B11011 B11012 B12004 D06004 6 B02032 B02033 R03000 B07062 B22043 B22062 D06005 5 B02031 R03000 B07062 B22004 B22031 D06006 3 D06003 D06002 B22063 D06007 6 B01012 B01014 D06008 B04024 B27003 B28003 D06008 3 B02034 B02035 B02036 D06020 8 B01075 D01011 D01012 B22042 B22120 B22121 B04075 B04065 D06021 7 B01075 D01011 D01012 B22122 B22123 B12001 D03002 D06022 5 B01075 D01011 D01012 B22038 B22039 D06023 8 B01015 D01023 D01011 D01012 B22038 B22039 B22120 B22121 D06024 4 D06020 R02000 B22038 B22039 D07001 2 D01031 D02011 D07002 2 D01032 D02011 D07003 3 D07001 R01000 D02005 D07004 3 D07002 R01000 D02005 D07005 3 D07001 R01004 D02005 D07006 3 D07002 R01004 D02005 D07007 2 D01031 D02012 D07008 2 D01032 D02012 D07009 2 D01031 D02013 D07011 16 B01063 B02001 D01011 D01012 D01024 B07006 B11001 B11016 B11017 B11002 B11041 B07006 B12001 B12003 B10052 B20009 D07012 4 R03000 B08023 B05021 B20001 D07013 7 R06000 B01064 B08014 B20061 B08014 B20061 B20018 D07014 2 R01000 B20019 D07015 3 R01000 D02005 B20002 D07016 2 R01000 B20020 D07017 2 R01000 B11070 D07018 13 B08016 R02000 B08017 D01012 R04000 B07006 B11001 B11002 B11041 B20009 R01000 B20001 D07014 D07020 3 D07011 D07014 D07016 D07021 9 D07011 D07012 D07013 D07014 D07015 D07016 D07017 D07018 D07015 D07030 2 B15001 B15002 D07031 7 B08022 B08023 B15001 B08023 B15001 B08023 B15002 D07041 7 D01001 B01015 D01024 D01011 D01012 D01070 D07030 D07042 9 D01001 B01015 D01024 D01011 D01012 B08021 B04025 D01070 D07031 D07043 7 D01001 B01015 D01024 D01011 D01012 D01074 D07030 D07044 9 D01001 B01015 D01024 D01011 D01012 B08021 B04025 D01074 D07031 D07060 2 B07061 B12030 D07061 3 D01031 R01005 D07060 D07062 3 D01032 R01005 D07060 D07063 2 B07061 B12130 D08001 3 D01033 D02011 B22042 D08002 3 D01034 D02011 B22042 D08003 3 D01035 D02011 B22042 D08004 3 D01036 D02011 B22042 D08005 2 D08004 D02024 D08006 8 B10004 B10061 B10063 B11001 B11002 B12004 B13003 B22042 D08007 4 D01055 D02011 B07062 B22042 D09001 3 D01037 R01000 D03011 D09002 3 D01038 R01000 D03011 D09003 3 D01037 R01000 D03012 D09004 3 D01038 R01000 D03012 D09005 4 D01037 D02004 R01000 D03013 D09006 4 D01038 D02004 R01000 D03013 D09007 4 D01037 D02004 R01000 D03014 D09008 4 D01038 D02004 R01000 D03014 D09011 3 D01039 R01000 D03011 D09012 3 D01039 R01000 D03012 D09013 4 D01039 D02004 R01000 D03013 D09014 4 D01039 D02004 R01000 D03014 D09015 3 D01040 R01000 D03011 D09016 3 D01040 R01000 D03012 D09017 4 D01040 D02004 R01000 D03013 D09018 4 D01040 D02004 R01000 D03014 D09019 4 D01031 B02003 R01000 D03011 D09020 7 D01031 B02003 R04000 B07003 B11003 B11004 B11005 D09030 7 B15004 B15005 R04000 B04015 B08006 B07004 B15003 D09040 3 D01075 D01076 D09030 D09041 4 D07041 D01075 D01076 D09030 D09042 4 D07042 D01075 D01076 D09030 D09044 4 D07044 D01075 D01076 D09030 D10001 5 D01042 D03031 D03032 R01026 D03025 D10002 5 D01042 D03031 D03032 R01009 D03023 D10003 5 D01042 D03031 D03032 R01006 D03023 D10004 5 D01042 D03031 D03032 R01003 D03024 D10005 5 D01042 D03031 D03033 R01000 D03025 D10006 5 D01042 D03031 D03033 R01000 D03023 D10007 5 D01042 D03031 D03033 R01000 D03024 D10008 8 D10011 R01019 D10012 B02150 B25079 B25080 B33032 B14045 D10009 3 D10011 R01015 D10012 D10010 3 D10011 R01005 D10012 D10014 3 D01072 D03041 D04011 D10015 13 D01072 B07024 B10002 D03041 R01003 D04032 B02152 B02024 B07004 B07004 B13003 R01003 D04033 D10016 13 D01072 B07024 B10002 D03041 R01012 D04032 B02152 B02024 B07004 B07004 B13003 R01012 D04033 D10020 6 D10022 D01011 D01013 D01021 D04034 D10021 D10022 4 B01007 B02019 B01033 B02172 D10023 17 D01072 B30021 B30022 B08012 B07024 B07025 B10002 R01012 D04032 R05002 B02152 B02024 B07004 B07004 B13003 R01012 D04033 D10050 13 D10051 D10052 R01000 D10053 R01004 D10054 B20010 D10052 R01015 D10053 D10052 R01004 D10053 D10195 3 D01250 D03250 D04250 D11001 9 D01051 B07002 B12001 B11001 B11002 B11031 B11032 B11033 B20041 D11002 4 D01065 D01066 D11003 D11004 D11003 5 B10070 B11001 B11002 B12001 B13002 D11004 12 R01000 B11034 R01000 B11035 R01000 B11075 R01000 B11076 R01000 B33025 R01000 B33026 D11005 13 B01008 B01023 D01021 D01011 D01013 B07010 B08009 B11001 B11002 B11031 B11036 B12101 B33025 D11006 6 B07010 B11001 B11002 B02064 B12101 B12103 D11193 16 D01197 D01011 D01012 D01023 B08004 B07004 B08021 B11001 B11002 B11031 B11034 B11035 B12001 B12003 B13003 B20041 D12001 2 D01043 D04001 D12002 2 D01043 D04002 D12003 2 D01042 D04003 D12004 2 D01042 D04004 D12005 2 D01042 B20014 D12006 2 D01044 D04005 D12007 2 D01042 D04006 D12010 6 B01007 B05040 B02021 B05041 B04001 B04043 D12014 8 D12010 D12011 R05056 D01023 B05042 B05052 D12012 D12013 D12016 3 D12010 D12011 D12015 D12018 3 D12010 D12011 D12017 D12020 11 D01047 D01048 B15015 B29002 B21076 R04012 B06030 R02012 B05030 B21075 B21066 D12021 6 D01047 R01003 D01049 B11012 B11011 B21067 D12022 15 D01047 B08022 B11012 B11050 B22070 B22026 D12041 B10050 B21068 B21071 B21072 B21073 D12042 B21062 B15011 D12023 7 D01047 R03003 B08022 B12061 B22050 B21069 B21085 D12024 11 D12020 B08060 B08022 B08060 B08022 B25014 B22101 B22097 B22098 B22099 B22100 D12025 11 D12019 B08060 B08022 B08060 B08022 B25014 B22101 B22097 B22098 B22099 B22100 D12026 19 D01046 D01011 D01013 D01023 D12031 R01004 D12030 B21110 D01023 D21027 B21111 D01023 D21027 B21112 D01023 D21027 B21113 D01023 D21027 D12027 9 D01047 R05009 D01023 B07021 B12061 B07021 B12061 B21085 B21070 D12031 8 B05034 B06034 B21109 B11081 B11082 B21101 B21102 B21103 D12032 4 B21120 B21121 B13055 B21122 D12033 4 B02104 B08022 B12063 B12065 D12042 6 B21077 B21078 B21079 B21080 B21081 B21082 D12045 21 B01007 B02019 B01096 B25061 B05040 D01011 D01013 D01021 B07002 B12180 B12181 B12182 B12183 B12184 B12185 B02174 B21086 B12186 B21087 B12187 B33043 D13009 3 B21001 R01000 B21001 D13010 3 B21036 R01000 B21036 D13031 4 B06002 B06012 R01000 B30001 D13032 4 B05002 B05012 R01000 D13031 D13041 9 B06002 R10000 R04000 B06012 R01000 B30001 B06012 R01000 B30001 D13042 4 B05002 B05012 R01000 D13041 D13043 11 B06002 B05002 B05012 R12000 R10000 R04000 B06012 R01000 B30001 R01000 B30001 D15001 5 B01011 D01011 D01012 D01023 D06001 D15002 5 B01011 D01011 D01012 D01023 D06004 D16001 10 D01011 B04004 D01023 B01021 B02041 B19001 B10051 B19002 B19003 B19004 D16002 15 B08021 B04001 B04002 B04003 B04004 B04005 B01033 B08021 B04001 B04002 B04003 B04004 B04005 B07002 B07002 D16003 10 R09000 B08011 B08007 R04000 B05002 B06002 B10002 B11002 B08007 B08011 D16004 11 R10000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B11031 B08007 B08011 D16005 9 R08000 B08005 B08007 B05002 B06002 B01026 B19001 B08007 B08005 D16006 12 R11000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B20011 B20012 B08007 B08011 D16007 10 R09000 B08011 B08007 R04000 B05002 B06002 B19005 B19006 B08007 B08011 D16008 11 R10000 B08001 B08007 B08023 R03000 B05002 B06002 B10002 B08023 B08007 B08001 D16009 11 R10000 B08011 B08007 B07002 B07002 R02000 B05002 B06002 B20041 B08007 B08011 D16010 8 R07000 B08011 B08007 B01022 B05002 B06002 B08007 B08011 D16011 17 R16000 B08011 B01022 B08007 R02000 B05002 B06002 B08021 B04001 B04002 B04003 B04004 B04005 B20090 B08021 B08007 B08011 D16020 5 B01023 B01025 B01027 D01011 D01012 D16021 23 D01023 B02041 B19001 B19007 B19005 B19006 B19008 B08005 B10004 B08005 B10004 B19007 B08005 B08021 B04075 B11040 B19007 R05004 B05021 B05021 R02002 B19003 B19004 D16022 23 B01032 B02041 B19001 B19010 R18000 B08021 B04014 B08005 D01023 B19005 B19006 B10004 B11041 B08021 B04075 B11040 B19008 R05004 B05021 B05021 R02002 B19003 B19004 D16026 2 D16020 D16021 D18001 2 D01025 B24011 D18003 4 D01026 B24005 B24004 B24021 D18004 6 D01025 B04023 B13011 B24005 B24004 B24022 D21001 6 B02101 B02114 B02105 B02106 B02107 B02121 D21003 4 B21051 B21014 B21017 B21030 D21004 4 D01031 B02003 R01000 D21003 D21005 12 B25004 B02121 B02122 B02123 B02124 B02125 B02126 B02127 B02128 B02129 B02130 B02131 D21006 4 B25001 B25002 B25003 B25005 D21007 8 B25009 B25010 B25011 B25012 B25013 B25015 B25016 B25017 D21008 3 B25006 B25007 B25008 D21009 2 B25018 B25019 D21010 13 B02101 B07002 B02102 B02103 B02104 B02105 B02106 B02107 B02108 B02109 B02110 B02132 B02133 D21011 3 B30031 B30032 B29002 D21012 2 R01000 B02135 D35001 4 B08035 B35001 B08036 D01001 D35002 4 B08035 B35001 B08036 B01033 D35003 6 B08021 B04001 B04002 B04003 B04004 B04073 D35004 7 B08021 B04004 B08021 B04004 B35000 D01001 B35011 D35005 7 B08021 B04004 B08021 B04004 B35000 B01001 B35011 D35006 7 B08021 B04004 B08021 B04004 B35000 B01003 B35011 D35007 9 B08021 B04004 B08021 B04004 B35000 B01001 R02000 B01002 B35011 D35010 3 D35002 D35003 D35007 dballe-7.7/extra/Makefile.in0000644000175000017500000003177612652630066012747 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = extra ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/m4_ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FC = @FC@ FCFLAGS = @FCFLAGS@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDBALLEF_VERSION_INFO = @LIBDBALLEF_VERSION_INFO@ LIBDBALLE_VERSION_INFO = @LIBDBALLE_VERSION_INFO@ LIBOBJS = @LIBOBJS@ LIBPQ_CFLAGS = @LIBPQ_CFLAGS@ LIBPQ_LIBS = @LIBPQ_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ WREPORT_CFLAGS = @WREPORT_CFLAGS@ WREPORT_LIBS = @WREPORT_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_FC = @ac_ct_FC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_doxygen = @have_doxygen@ have_gperf = @have_gperf@ have_latex2html = @have_latex2html@ have_rst2html = @have_rst2html@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mysql_config = @mysql_config@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ tabledir = @tabledir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ aof bufr crex csv \ runtest \ test-bufr-table.txt \ test-crex-d-table.txt \ test-crex-table.txt \ test-repinfo1.csv \ test-repinfo2.csv all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extra/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign extra/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *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);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool 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-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am .PRECIOUS: Makefile # 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: dballe-7.7/extra/bufr/0000755000175000017500000000000012652630043011675 500000000000000dballe-7.7/extra/bufr/synop-rad2.bufr0000644000175000017500000000051412652630043014473 00000000000000BUFRLU– €Ç` ë¦"(*¬–¦'ª¢"©¾bŒpÍÂ0Ê€0*LÁH‰xüPbd†ø0‘³ÿ÷ðàßÿàv oÿjhç•ÿÿÿü¦Æ°)À2lã‘´ÿø×ÿÇÐÿÿÿ÷ˆ _ÿüŸÇÿÿÿÀÕ_Àþ³þ ãðQ€?@ÿÿÀÿûÿýý¿ÿÿÿÿÿÿÿÿÿÿûÿÿÿÄþÕàUûûW‚ ñ+Á6é–€¥jU [ÿߪõ©Ü)ñ‰ÿü[ÿÿÿÿÿÿÿÿÿþ,<ÿà¿èôúýÿÿ¯þ (ßÿÿÿÿÿÿþÿÿÿÿïÑÿÿÿÿÿÿHoÿÿÿÿõý‰ÿÿà@ÿÿÿÿ€7777dballe-7.7/extra/bufr/README0000644000175000017500000000073112652630043012476 00000000000000This directory contains test data, at least one file per supported report type. Samples have been selected as the ones with less unset values in the available dataset. Some extra cases are there to test regressions; they are listed here: obs4-142.13803.bufr Contains a longitude of -100.230000, which in the past was converted to -10.023 because the internal storage space was not long enough to store the initial '-'. The dry bulb temperature had a similar bug. dballe-7.7/extra/bufr/obs0-1.11188.bufr0000644000175000017500000000030212652630043014152 00000000000000BUFRÂb€ 4}\@LœdYt13577 ÂLjKpF€Ç  –A" A"!T ¯«€ÈE—Bd|àçÿøMào±-òÀ«Ûøúæ6@`<<·€õÿÿ€ @1£F4hÑ£F.4Ùñ£P›•XѪƫR­Z±£7777dballe-7.7/extra/bufr/obs255-255.0.bufr0000644000175000017500000000022012652630043014155 00000000000000BUFRÈÿ 8ÀÁÃÂÀÁ !!À!ÃÀÀÁÀ:P@ @ &@€õÍ ÍbIE¦@Ç€7777dballe-7.7/extra/bufr/temp-windprof1.bufr0000644000175000017500000000140612652630043015352 00000000000000BUFRb€` 64`}ñJÛIÀjËØ10678 Nâ°)@F€Á ÕAÕšSO¾)[fÕÉ\ä™FÏ–À‹`J0KUcpJ0%#ªñ˜'\|Õ?ÈðÐ >ÊŸæz ø¡ÕOõ1Ä‚Xª§üƒA-¹SþŠ•@—T©ÿeÓ°KÐ-U nX%Àª€I9päU@,¨Ú zJ V}Ä¥P(e¨•'4€ÙTÌ%à›`dªfN1UB’€&è*€øK„t•?ø&â º ŸúBà…Oû Iƒwú·þ†…HÁ;SþŶ€€š©ÿ£Ád@Nð\Tÿ¢¶¨'4ªÁ0]˜ÄU?Ü”/ì ÞJŸð@‡óEOø Œzƒ¢§ú‹j,$_ÿÿÿÿà hÑ£F͘ÓãF4hÀ7777dballe-7.7/extra/bufr/obs4-145.4.bufr0000644000175000017500000000035612652630043014021 00000000000000BUFRîb€‘ 4‘}Y#r8bì82DPCV2RA îV–FN€=>F?    " #   )–AÉA!N2DPCV2RAJBNYR3RAæ†kÿü}Y2¦$L¥~Vÿÿÿÿ•?ÿÿàÄ7øÑ£Fÿ4hÑ£FøÑ¿ÿÿÿÿà7777dballe-7.7/extra/bufr/bufr30000644000175000017500000000036312652630043012563 00000000000000BUFRòb€   4 }Ky€IGÄmðˆV2PJ6 òyty€ÖF@€Á$    ????! "%&$–A' A'!`V2PJ6 ê[ÌÂRXWÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿà€cK—4hÑ£Zµ4hÑ£F4hÑ£F4hÑ£F4hÀ7777 dballe-7.7/extra/bufr/temp-gts2.bufr0000644000175000017500000001405012652630043014317 00000000000000BUFR([  €É4"ÿÿÿÿÿÿÿÿˆ¨“ìàWBŠ”`Èÿÿÿÿü$O2WÿÿÀ ÿÀÉÿÿÿÿÿÿÿû~;Eû ¿ÿ«ÿÿÿÿÿÿÿÿÿÿÿû¬¿ÿ†tÿÿÿÿÿÿÿû…FŸÿÿÿÿÙÿÿÿÿÿÿÿÿÿÿÿú¼ÿÿ†zÿÿÿÿÿÿÿûƒ;;_ÿÿÿÿ†ÿÿÿÿÿÿÿû…-Ÿÿÿÿÿ¼ÿÿÿÿÿÿÿÿÿÿÿúÐÿÿ†Šÿÿÿÿÿÿÿû€»&ÿÿÿÿ†ÿÿÿÿÿÿÿû€?ÿÿÿÿÌÿÿÿÿÿÿÿÿÿÿÿû4?ÿ†^ÿÿÿÿÿÿÿûwûÿÿÿÿÿ†,ÿÿÿÿÿÿÿû}› ÿÿÿÿ×ÿÿÿÿÿÿÿÿÿÿÿú¼ÿ«ÿÿÿÿÿÿÿÿÿÿÿú”ÿ$ÿÿÿÿÿÿÿÿÿÿÿúøÿÿ† ÿÿÿÿÿÿÿûWzÑÿÿÿÿ† óÿÿÿÿÿÿÿûUJÒÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿúøÿÿ Pÿÿÿÿÿÿÿÿÿÿÿú€¿ÿíÿÿÿÿÿÿÿÿÿÿÿúlÿßÿÿÿÿÿÿÿÿÿÿÿû ÿ†lÿÿÿÿÿÿÿúç꯯ÿÿÿÿ!ÿÿÿÿÿÿÿÿÿÿÿúøÿ†ôÿÿÿÿÿÿÿúá ¸oÿÿÿÿŸÿÿÿÿÿÿÿÿÿÿÿû„¿ÿ†ÿÿÿÿÿÿÿúØJÍÿÿÿÿTÿÿÿÿÿÿÿÿÿÿÿû ?ÿ×ÿÿÿÿÿÿÿÿÿÿÿû4ÿdÿÿÿÿÿÿÿÿÿÿÿú¼¿ÿºÿÿÿÿÿÿÿÿÿÿÿúä!¿ÿ†œÿÿÿÿÿÿÿúžÊ‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúD ÿ†ÔÿÿÿÿÿÿÿúÊ€ÿÿÿÿÅÿÿÿÿÿÿÿÿÿÿÿúä!¿ÿ†fÿÿÿÿÿÿÿú} n_ÿÿÿÿWÿÿÿÿÿÿÿÿÿÿÿú¼?ÿ† ÿÿÿÿÿÿÿú{Êl/ÿÿÿÿ‡éÿÿÿÿÿÿÿú‰ŠvÌ¿ÿ¨ÿÿÿÿÿÿÿÿÿÿÿü¿ÿ…ÿÿÿÿÿÿÿÿÿÿÿüˆÿ†gÿÿÿÿÿÿÿú†jdÿÿÿÿbÿÿÿÿÿÿÿÿÿÿÿûÀ ÿÿÿÿÿÿÿÿÿÿÿÿüL%ÿÿÿÿÿÿÿÿÿÿÿÿü%ÿ†ÿÿÿÿÿÿÿú”*hoÿÿÀ‡ßÿÿÿÿÿÿÿÿâ*#äû8言Ÿƒð:¿ÿÿÿÿ Ì•ÿÿð¿ÿðí_ÿÿÿÿÿÿÿþàöÖU_ÿà@äŸÿÿÿÿÿÿÿÿÿÿÿþŒ ÿà@Çßÿÿÿÿÿÿÿÿÿÿÿþ}ßÿà@­Ÿÿÿÿÿÿÿÿÿÿÿÿþ ?ÿအÿÿÿÿÿÿÿþàÕÿÿÿÿà@Ž_ÿÿÿÿÿÿÿÿÿÿÿþ¥ïÿá€ßÿÿÿÿÿÿÿþàÓ‡ÿÿÿÿà@u_ÿÿÿÿÿÿÿÿÿÿÿþæOÿà@_ÿÿÿÿÿÿÿÿÿÿÿÿ Ÿÿà@üÿÿÿÿÿÿÿÿÿÿÿþúïÿà@èÿÿÿÿÿÿÿÿÿÿÿÿ,ÿÿà@¶ÿÿÿÿÿÿÿÿÿÿÿÿ6_ÿဥßÿÿÿÿÿÿÿþÕgÿÿÿÿÿÿà@ŸŸÿÿÿÿÿÿÿÿÿÿÿþÿà@†ŸÿÿÿÿÿÿÿÿÿÿÿþÒÿÿà@rŸÿÿÿÿÿÿÿÿÿÿÿþ–Ÿÿà@^Ÿÿÿÿÿÿÿÿÿÿÿÿþ‘/ÿà@I_ÿÿÿÿÿÿÿÿÿÿÿþ /ÿá€_ÿÿÿÿÿÿÿþÐz¼+ÿÿÿÿà@ößÿÿÿÿÿÿÿÿÿÿÿþ} _ÿà@®_ÿÿÿÿÿÿÿÿÿÿÿþ‘ ¯ÿဩ_ÿÿÿÿÿÿÿþȪ¹Óÿÿÿÿá€~ßÿÿÿÿÿÿÿþÅ»³ÿÿÿÿá€iŸÿÿÿÿÿÿÿþÄ"Á·ÿÿÿÿà@,_ÿÿÿÿÿÿÿÿÿÿÿþ–ÿà@ÿÿÿÿÿÿÿÿÿÿÿþ¥/ÿá€ÿÿÿÿÿÿÿþ¾Z»ÇÿÿÿÿအŸÿÿÿÿÿÿÿþ³j°Kÿÿÿÿà@Tÿÿÿÿÿÿÿÿÿÿÿþ´oÿà@.Ÿÿÿÿÿÿÿÿÿÿÿÿþ¥ÿá€(_ÿÿÿÿÿÿÿþ¨R¢Ûÿÿÿÿà@Ÿÿÿÿÿÿÿÿÿÿÿÿþ¯ßÿဟÿÿÿÿÿÿÿþ¨¢£+ÿÿÿÿà@ _ÿÿÿÿÿÿÿÿÿÿÿþª ÿá€òŸÿÿÿÿÿÿÿþ¥ªŸkÿÿÿÿà@íŸÿÿÿÿÿÿÿÿÿÿÿþà ¯ÿá€Ý_ÿÿÿÿÿÿÿþ¥ZžSÿÿÿÿá€Æßÿÿÿÿÿÿÿþ¨¢ Óÿÿÿÿà@º_ÿÿÿÿÿÿÿÿÿÿÿþá ?ÿà@—_ÿÿÿÿÿÿÿÿÿÿÿþðÿà@ƒ_ÿÿÿÿÿÿÿÿÿÿÿþõ ÿÿဂÿÿÿÿÿÿÿþ¦š;ÿÿÿÿà@~_ÿÿÿÿÿÿÿÿÿÿÿÿ "ÿÿÿÿÿÿÿÿÿøŠˆù>Îyc*4°Š/ÿÿÿÿÀDò…ÿüŸÿüü×ÿÿÿÿÿÿÿÿ´F² ÀkÿøùgÿÿÿÿÿÿÿÿÿÿÿÿÐÿøõWÿÿÿÿÿÿÿÿÿÿÿÿ€ÿø`ò7ÿÿÿÿÿÿÿÿµ³Bÿÿÿÿø`ð§ÿÿÿÿÿÿÿÿµYÿÿÿÿÿÿøðWÿÿÿÿÿÿÿÿÿÿÿÿµÀ?ÿø`ï·ÿÿÿÿÿÿÿÿµ³°Ñÿÿÿÿø`ì—ÿÿÿÿÿÿÿÿµï°ÿÿÿÿøë§ÿÿÿÿÿÿÿÿÿÿÿÿ¾€kÿø`àgÿÿÿÿÿÿÿÿµŸ®ÿÿÿÿø`ÖÿÿÿÿÿÿÿÿµŸ¬qÿÿÿÿøÏ×ÿÿÿÿÿÿÿÿÿÿÿÿÉÁ7ÿøÆÇÿÿÿÿÿÿÿÿÿÿÿÿÑAÿøµ—ÿÿÿÿÿÿÿÿÿÿÿÿÓÁ7ÿø±‡ÿÿÿÿÿÿÿÿÿÿÿÿ×Kÿø`“‡ÿÿÿÿÿÿÿÿ±&­¢ÿÿÿÿøŒ÷ÿÿÿÿÿÿÿÿÿÿÿÿØÁ³ÿøƒ—ÿÿÿÿÿÿÿÿÿÿÿÿÑAŸÿøz‡ÿÿÿÿÿÿÿÿÿÿÿÿÓÁ³ÿør·ÿÿÿÿÿÿÿÿÿÿÿÿÐÛÿø`f7ÿÿÿÿÿÿÿÿ­4©Lÿÿÿÿø]wÿÿÿÿÿÿÿÿÿÿÿÿÒ‚/ÿøKWÿÿÿÿÿÿÿÿÿÿÿÿÌBCÿø`Gçÿÿÿÿÿÿÿÿª§ÿÿÿÿøG—ÿÿÿÿÿÿÿÿÿÿÿÿÓÂÿø?ÇÿÿÿÿÿÿÿÿÿÿÿÿÌB/ÿø`8çÿÿÿÿÿÿÿÿ¨4¦¤ÿÿÿÿø`7ÿÿÿÿÿÿÿÿ¨¦†ÿÿÿÿø`5'ÿÿÿÿÿÿÿÿ¨R¦Âÿÿÿÿø4‡ÿÿÿÿÿÿÿÿÿÿÿÿË¿ÿø`1gÿÿÿÿÿÿÿÿ§”¦ÿÿÿÿø/×ÿÿÿÿÿÿÿÿÿÿÿÿÕÿøp.—ÿÿÿÿÿÿÿÿ§Æ¦6ÑBWÿø-WÿÿÿÿÿÿÿÿÿÿÿÿÒ‚Wÿø`,ÿÿÿÿÿÿÿÿ¨p¦àÿÿÿÿø*‡ÿÿÿÿÿÿÿÿÿÿÿÿȃÿø&ÇÿÿÿÿÿÿÿÿÿÿÿÿÍ‚Óÿø`$Gÿÿÿÿÿÿÿÿ¨f¦rÿÿÿÿøp ‡ÿÿÿÿÿÿÿÿ©¦¸ÇC$‰ÿÿÿÿÿÿÿÿþ"¢>O³^pÉ7 &¢É»ÿÿÿÿð‘<¡_ÿÿ+ÿÿG}ÿÿÿÿÿÿÿÿíom$c ÿþFÿÿÿÿÿÿÿÿÿÿÿÿâ€)ÿþFeÿÿÿÿÿÿÿÿížíGÿÿÿþEMÿÿÿÿÿÿÿÿÿÿÿÿãÀÿþDqÿÿÿÿÿÿÿÿíœmÿÿÿÿþC©ÿÿÿÿÿÿÿÿí¨íÿÿÿÿþBAÿÿÿÿÿÿÿÿÿÿÿÿé`)ÿþ@ÿÿÿÿÿÿÿÿÿÿÿÿë]ÿþ>åÿÿÿÿÿÿÿÿí…ìÖÿÿÿÿþ>1ÿÿÿÿÿÿÿÿí—l„ÿÿÿþÿÿÿÿÿÿÿûWzêÿÿÿÿ† ÿÿÿÿÿÿÿûUŸÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿú”ÿÿ Æÿÿÿÿÿÿÿÿÿÿÿø(ÿ {ÿÿÿÿÿÿÿÿÿÿÿýÿ 5ÿÿÿÿÿÿÿÿÿÿÿû4ÿÿ ïÿÿÿÿÿÿÿÿÿÿÿø?ÿ ¤ÿÿÿÿÿÿÿÿÿÿÿûèÿÿ hÿÿÿÿÿÿÿÿÿÿÿýdÿÿ ÿÿÿÿÿÿÿÿÿÿÿø ¿ÿ Üÿÿÿÿÿÿÿÿÿÿÿø´ÿÿ  ÿÿÿÿÿÿÿÿÿÿÿýPÿ ZÿÿÿÿÿÿÿÿÿÿÿøP¿ÿ ÿÿÿÿÿÿÿÿÿÿÿý¿ÿ† âÿÿÿÿÿÿÿûêéÏÿÿÿÿ Ýÿÿÿÿÿÿÿÿÿÿÿü°¿ÿíÿÿÿÿÿÿÿÿÿÿÿý( ¿ÿ±ÿÿÿÿÿÿÿÿÿÿÿü°¿ÿHÿÿÿÿÿÿÿÿÿÿÿüœÿÿÿÿÿÿÿÿÿÿÿÿütÿÿäÿÿÿÿÿÿÿÿÿÿÿü°¿ÿ…ÿÿÿÿÿÿÿÿÿÿÿüt¿ÿÿÿÿÿÿÿÿÿÿÿÿü°¿ÿšÿÿÿÿÿÿÿÿÿÿÿüL¿ÿ†ÿÿÿÿÿÿÿúÊŠ/ÿÿÿÿ–ÿÿÿÿÿÿÿÿÿÿÿüœ?ÿ†<ÿÿÿÿÿÿÿú´ ¥ÿÿÿÿÿ#ÿÿÿÿÿÿÿÿÿÿÿüL¿ÿØÿÿÿÿÿÿÿÿÿÿÿüt?ÿãÿÿÿÿÿÿÿÿÿÿÿüÿÿ†pÿÿÿÿÿÿÿú}ªn_ÿÿÿÿ†aÿÿÿÿÿÿÿú‚ roÿÿÿÿ\ÿÿÿÿÿÿÿÿÿÿÿüt/¿ÿ‡ ÿÿÿÿÿÿÿú~JkŒ8)ÿäÿÿÿÿÿÿÿÿÿÿÿü`<¿ÿ†ÚÿÿÿÿÿÿÿúŒ v/ÿÿÿÿ¨ÿÿÿÿÿÿÿÿÿÿÿü°/¿ÿ†ÿÿÿÿÿÿÿú‚ªcoÿÿÿÿ{ÿÿÿÿÿÿÿÿÿÿÿüt9ÿÿXÿÿÿÿÿÿÿÿÿÿÿüØ*¿ÿ0ÿÿÿÿÿÿÿÿÿÿÿü`.ÿ†+ÿÿÿÿÿÿÿú…Ê`Oÿÿÿÿ‡þÿÿÿÿÿÿÿú“ŠgÌt)@«ÿÿÿÿÿÿÿÿÿâ*#äû8߃ƒ ¤LŒ+¿ÿÿÿÿ Êÿÿð/ÿðöÿÿÿÿÿÿÿþÝÖ^¯ÿáÀêßÿÿÿÿÿÿÿþàÎÕÞŸÿá€ПÿÿÿÿÿÿÿþáæÔŸÿÿÿÿà@¸ßÿÿÿÿÿÿÿÿÿÿÿþUÿÿà@¡ÿÿÿÿÿÿÿÿÿÿÿþ7¯ÿà@ŠŸÿÿÿÿÿÿÿÿÿÿÿþ‚_ÿà@qŸÿÿÿÿÿÿÿÿÿÿÿþ¯ÿà@\_ÿÿÿÿÿÿÿÿÿÿÿþÿÿà@EßÿÿÿÿÿÿÿÿÿÿÿþU¯ÿà@Ÿÿÿÿÿÿÿÿÿÿÿÿþdïÿá€_ÿÿÿÿÿÿÿþØÍÿÿÿÿà@êŸÿÿÿÿÿÿÿÿÿÿÿþ–?ÿá€æßÿÿÿÿÿÿÿþØËÿÿÿÿà@ªßÿÿÿÿÿÿÿÿÿÿÿþ¯ÿဓÿÿÿÿÿÿÿþÕÞÅwÿÿÿÿà@ÿÿÿÿÿÿÿÿÿÿÿþ ÿá€xßÿÿÿÿÿÿÿþÖ~ÀŸÿÿÿÿá€_ßÿÿÿÿÿÿÿþÕR¾«ÿÿÿÿဟÿÿÿÿÿÿÿþÒÒ¹Óÿÿÿÿà@ÍŸÿÿÿÿÿÿÿÿÿÿÿþÍ _ÿá€_ÿÿÿÿÿÿÿþÉJ½“ÿÿÿÿà@m_ÿÿÿÿÿÿÿÿÿÿÿþÈ ÿá€eßÿÿÿÿÿÿÿþÇj¿›ÿÿÿÿá€`ßÿÿÿÿÿÿÿþÇBºÃÿÿÿÿà@&ÿÿÿÿÿÿÿÿÿÿÿþæ¿ÿá€"_ÿÿÿÿÿÿÿþÃ2´[ÿÿÿÿà@ÖÿÿÿÿÿÿÿÿÿÿÿþÒ¿ÿá€Ò_ÿÿÿÿÿÿÿþºê±‹ÿÿÿÿှ_ÿÿÿÿÿÿÿþ¸j³»ÿÿÿÿဟÿÿÿÿÿÿÿþ´ú±³ÿÿÿÿà@fßÿÿÿÿÿÿÿÿÿÿÿþáÿá€Tÿÿÿÿÿÿÿþ¬:¨ßÿÿÿÿà@,ÿÿÿÿÿÿÿÿÿÿÿþð ÿá€ÿÿÿÿÿÿÿþ¥Ò¡ÿÿÿÿÿà@ßÿÿÿÿÿÿÿÿÿÿÿþæ ÿà@_ÿÿÿÿÿÿÿÿÿÿÿþë¯ÿà@üŸÿÿÿÿÿÿÿÿÿÿÿþæÿá€õÿÿÿÿÿÿÿþ¤âŸkÿÿÿÿá€â_ÿÿÿÿÿÿÿþ¦ê «ÿÿÿÿà@Úßÿÿÿÿÿÿÿÿÿÿÿÿÿá€Î_ÿÿÿÿÿÿÿþ£¢œ›ÿÿÿÿà@¼ßÿÿÿÿÿÿÿÿÿÿÿÿ ïÿ်_ÿÿÿÿÿÿÿþ£òœ#ÿÿÿÿဨßÿÿÿÿÿÿÿþ¡š™Ëÿÿÿÿဥÿÿÿÿÿÿÿþ¢²šãÿÿÿÿà@£ßÿÿÿÿÿÿÿÿÿÿÿÿ/ÿလ_ÿÿÿÿÿÿÿþ¡êšÿÿÿÿà@Œÿÿÿÿÿÿÿÿÿÿÿÿ Ÿÿà@‡ÿÿÿÿÿÿÿÿÿÿÿÿ'¿ÿစßÿÿÿÿÿÿÿþ¥úœ›ÿÿð7777dballe-7.7/extra/bufr/temp-bad3.bufr0000644000175000017500000000025612652630043014254 00000000000000BUFR®b€e  4e}²1€F£üliè06260 ®1–bF€É–A A!@ ‚(#푌±§ Gø”þÿÿÿüßÿÿÿÿÿÿÿ€ €ñð Ñ£F4hÑ£F4hÀ7777dballe-7.7/extra/bufr/synop-evapo.bufr0000644000175000017500000000472612652630043014766 00000000000000BUFR Ö[  €ÇP ®"#¤©"©ª§/³˜>šq`ÿÿÏ%>øÿÿÿÿÿÿÿût;OÿÿóèÿÿÿÿþÈ$O.X$T PÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÁÿþÙOÿÿÿýú?ûÿÿÿÿø ÿÿÿÿÿÿÿÿÿÿÿÿÿnÿÿÁ?·ü>þßÿÿÿÿÿÿÿÿ¿Gÿïÿÿÿÿÿÿÿÿÿÿÿýú?ÿÿÿÿÿÿÿÿÿÿÿü~DFBOLU ßg0 w¦… YMÿÿây—ÙÿÿÿÿÿÿÿöçÖ—ßÿÿÿÿÿÿÿÿøÿÿÿðÿäÉÿÿÿÿÿÿÿÿÿÿÿÿÿiëÿÿÿþýýÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿÿàŸØŒ_oÿÿÿÿÿÿÿÿߣÿ÷ÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿÿþ?"*!§©*¦/³˜9 Âù°-ðÿÿÈi>ûîßÿÿÿÿÿÿûJûJÿÿñÿÿÿÿþ”$O(X&€þGüŸÿÿÿÿÿÿÿÿÿþOÿöpSýÐHÿÿÿÿÀ`?ÿÿÿÿÿÿÿÿÿÿÿÿûCÿþ ýÀ ÷öÿÿûLÀ?ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿàò"ÒšJ² ™û8€býÌ)d1/ÿüCßÿ¿Ïÿá4ãÿÿµc³ûÿÿÿ.çÿÿÿÿÿõÀJû‚$ Œ2¨€ ÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿ“ÿý¡oÿÿÿûô ÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿþÓ×ÿÿ‚a@ýý¿ÿÿÿÿÿÿÿÿ~ÿßÿÿÿÿÿÿÿÿÿÿÿûôÿÿÿÿÿÿÿÿÿÿÿøüˆÄ–‚¤¦@@@@@@@@@@@@@@@@¾Î`æƒ £%VÓÿÿßÿðAøM@ÿí,î¿ÿÿÇÑÿÿÿÿÿø<‘ÿàÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÉÿþÈÿÿÿýúÿÿÿÿø ÿÿÿÿÿÿÿÿÿÿÿÿÿdëÿÿÁ?·ü>þßÿÿÿÿÿÿÿÿ¿Bÿÿÿÿÿÿÿÿÿÿÿýú?ÿÿÿÿäèÿÿÿÿü~D–BALIKESIR _g0 \N„ôû`'Mÿÿ›¾v§Ù¿ÿÿÿÿÿÿöë–Ó?ÿÿçÐÿÿÿþ¸)`d  P"Uÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿ‡ÿýµ¼ÿHôÿÿÿÿð/ÿÿÿÿÿÿÿÿÿÿÿÿþÜGÿÿ‚f@ ýý¿ÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿûôÿÿÿÿ6Œÿÿÿÿÿøü‰@–’¤¦Š’¤@@@@@@@@@@@@¾Î`¢' 6BÚÃÿÿGÿïÔøM4¿ÿíW­ÿÿÏ¡ÿÿÿÿÿúP RÆ¡@ ˜Â€ùòÿÿÿÿÿÿÿÿÿøÿÚaÿÿÿÿ¿AÔÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿí:ÿÿø'ö¯'ßÛÿÿí1ÿïÿ÷èÿýÿÿÿÿÿÿÿÿÿÿÿÿ¿Gÿÿÿÿÿÿÿÿÿÿÿÿ€È—)i *h*D ìàf‰fðž“´пÿóNàüÿÿÿÿÿÿþÝšÜ[ÿÿüúÿà!ÿÿ×,k %q  ÿò?äÿÿÿÿÿÿÿÿÿÿñÿ·€_èÂ~°ÿÿÿÿþGÿÿÿÿÿÿÿÿÿÿÿÿÿÛ¡ÿÿðOìP¯¿·ÿÿÚcþÿïÐ ÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿ‘/PQ–SÓ’ÐTRTÐT‹SQVQWÙÀÌ´¡AY ”ÿãÿýü/ÿ  &?ÿý¯Í­wÿÿøÈ?ÿÀÿÿ® X—(H„Á•@ÿäÉÿÿÿÿÿÿÿÿÿÿâÿÿk{?Єýýÿÿÿÿü+ÿÿÿÿÿÿÿÿÿÿÿÿÿµôÿÿàŸÚ¿oÿÿÿÿÿÿÿÿߣÿ÷ÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿÿþ?"i)¤¤©*/³˜fÂ¥Vp2dÿÿÇÁ?ãê¿ÿÿÿÿÿÿû^«KOÿÿóèÿÿÿÿþ”$O(&€þGüŸÿÿÿÿÿÿÿÿÿþOÿöž¿ÿÿÿïÐoÿÿÿÿÀ`?ÿÿÿÿÿÿÿÿÿÿÿÿû]ÿþ ý¿à÷öÿÿÿÿÿÿÿÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿïÑÿÿÿÿýŸÿÿÿÿÿàò'R Ê"Jqû8€aŠ´'¤íoÿüæó½¿‡ÿÿÿÿÿÿÿ·R·HÿÿÿGÿø,ÿõÀPñ;eˆ$ˆ P(†M€ÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿ‹ÿýºl¾ÿBô §ÿÿÿÿð ÿÿÿÿÿÿÿÿÿÿÿÿþÝKÿÿ‚b0 ýý¿ÿþÓðHÿÿ~„ŸÿÿÿÿÿÿÿÿÿÿÿûôÿÿÿÿÿÿÿÿÿÿÿøüŠŽ‚´’‚œ¨Š @@@@@@@@@@@¾Î`= ]R¬«ÿÿ%o¨ÿÿÿÿÿÿí‡-R¿ÿÿÇÑÿÿÿÿÿûà R¾¹@@™€% ªÿ#þOÿÿÿÿÿÿÿÿÿÿÿûO_ÿÿÿ÷è>Oÿÿÿÿà0ÿÿÿÿÿÿÿÿÿÿÿÿý¨ïÿÿþÕàûûÿÿÿÿÿÿÿþý?ÿÿÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿþeÿÿÿÿÿðù‰ =IU4€€€€€€€€€€€€€}œ À0uFÈ5€·ÿþt™Ú BÿÿÿÿÿÿÿÛìÛØÿÿÿŸCÿüŸÿúà ¥²€BˆNTþGüŸÿÿÿÿÿÿÿÿÿþ/ÿöö0Ëý%Ð%ŸÿÿÿÿÀ`ÿÿÿÿÿÿÿÿÿÿÿÿÿû|ÿÿþ ý÷öÿÿûLÁ‹ÿýú ÿÿÿÿÿÿÿÿÿÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿàò+’JšZ*r"*’ªqû8€`’¨):°üÿüöSÛ?Ïÿÿÿÿÿÿÿ¸µ´ëÿÿÿ.çÿÿÿÿÿòÀ1Kåd ˜2¨?üù?ÿÿÿÿÿÿÿÿÿüÿíøÿÿÿÿß ê?ÿÿÿÿ€Àÿÿÿÿÿÿÿÿÿÿÿÿ÷?ÿüû€Wïíÿÿÿÿÿÿÿÿûô xÿÿÿÿÿÿÿÿÿÿÿÿߣÿÿÿÿû1§ÿÿÿÿÿÀà7777dballe-7.7/extra/bufr/obs4-142.1.bufr0000644000175000017500000000024212652630043014005 00000000000000BUFR¢b€Ž  4Ž}YÒ0$8k¬tACA872 ¢ < 4F€Ë–A A!8ACA872 ï« €–ºÇA!ÁÁ+¢jpHŸÿÿÿÿà hÑ£F4hÓãF4hÀ7777dballe-7.7/extra/bufr/synop-tchange.bufr0000644000175000017500000000034012652630043015251 00000000000000BUFRà×ß €ÇPµ 1( ¬¢©'"¾bŒ†2:€Ä"ÄdÌC[ö_ÿÿÿÿøCXQ_ÿÿÿ€Kÿÿÿÿÿÿÿÿøÿò?äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðýüYÿÀÿÿÿÀ2Ò?ÿßÒ?ÿÀú0Oì2O¿·ÿÿÝ3þ?ÿïÑÿûÿÿÿÿÿÿÿÀÿÿÿÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþè7777dballe-7.7/extra/bufr/synop-gtscosmo.bufr0000644000175000017500000000055412652630043015505 00000000000000BUFRlN€ Ù ÿÿ¬G  :€ÁZ„ÂÂ#Â$Â/Â0Â%Â8Â+ *Â,„AÂ-Â.„A…þÿÿÿÿÿú °±´2·/²L0¶²7긄 Ð ó“}¿xÿÿÿÿÿÿÿàØ_í`ÿÿÿüúÿÿÿÿÿÿÿäñþ<#|ïøàüxÞ€<ÿùÿòÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€½þ¼Þ/ÿÿÿÿÿÿÿßëÀÿÿÿÿÿÿÿßÓàÿÿýý>?ÿÿÿÿþ<^þßhðÿûûÿÿÿÿÿÿÿÿÿÿÿí1ÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø7777dballe-7.7/extra/bufr/gts-acars-uk1.bufr0000644000175000017500000000017612652630043015063 00000000000000BUFR~J€ÿ  ÿÿ«øª  &€Ë $ L>@  4LH968 ²L-öŸž"EÆæÀ¦¥€B)ßÿÿÿÿÿÿÿÿýTÌÌÜÔ€ƒù€ 7777dballe-7.7/extra/bufr/generic-onlystation.bufr0000644000175000017500000000020612652630043016470 00000000000000BUFR†Èÿÿè €ÂÀDgeneric @S^H™X]]Y[Ý][Ûˆ A3˜¬ƒø7777dballe-7.7/extra/bufr/ecmwf-ship-1-12.bufr0000644000175000017500000000036212652630043015116 00000000000000BUFRòb€   4 }ÓM Gsaö D5BO9 òM2 F@€Á$    ????! "%&$–A' A'!`D5BO9 -ëîši‘BIWÿÿÿÿïþ@ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿà€cF4hÑ£F4hÑ£F4hÑ£F4hÑ£F4hÀ7777dballe-7.7/extra/bufr/test-buoy1.bufr0000644000175000017500000000046212652630043014513 00000000000000BUFR2b€ƒ  4ƒ}™\P ëdv61691 2\Z\äF €Á# Æ–ADÉAD!Àx}€À öepÌýGßÿÿÿ‘2ÿÀ œÉ?ÿg€g‚±²}€…s€Œa€O€Os‚±²|j+Ä|[€UsI>g€¤ËÃI— ŽÛº=b1-ô$çïÕŸ€ô$YUs= g€s÷€Éjhh½ŽI—YÛºÉjY[€s÷€Éj€ÕŸ€ô$YÃI—çïÉj€s÷€0ÔUsI>0Ô$Ÿ¤Ë€ÛºÃ1-ÛºÕŸ€ÛºÕŸ€¤Ë€¤Ë€˜–€±€I>$Ÿ+Ä~±²~±²}ú—ú—€Os€…€O‚7 €js÷€Ûº Žçï½5€½5€¤Ë€±Ã=btP€…€…˜ïÕø˜ï$øçï[€0Ôj7 €I>ÛºÃô$YÕŸY¤Ë€7777BUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUUUUUUUUUUUUPUUUUUQUUð `g€¤ËÃY Ž1-ÛºÕŸ€ô$ô$ÕŸ$øŒa€UsI>g€g‚±²}€…s€Œa€O€Os‚±²|j+Ä|[€UsI>g€¤ËÃI— ŽÛº=b1-ô$çïÕŸ€ô$YUs= g€s÷€Éjhh½ŽI—YÛºÉjY[€s÷€Éj€ÕŸ€ô$YÃI—çïÉj€s÷€0ÔUsI>0Ô$Ÿ¤Ë€ÛºÃ1-ÛºÕŸ€ÛºÕŸ€¤Ë€¤Ë€˜–€±€I>$Ÿ+Ä~±²~±²}ú—ú—€Os€…€O‚7 €js÷€Ûº Žçï½5€½5€¤Ë€±Ã=btP€…€…˜ïÕø˜ï$øçï[€0Ôj7 €I>ÛºÃô$YÕŸY¤Ë€7777dballe-7.7/extra/bufr/synop-oddprec.bufr0000644000175000017500000000033412652630043015263 00000000000000BUFRÜJ Ù  €ÇP° f£²©º¡2¹70¹2/³‚Pzò;30p089º ÿü?ýµ€{Gÿû4+1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿò?äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_ÿÿÿþýÿÿÿÿÀÿÿÿÿÿßÒ?ÿßÒ?ÿÿÿðOìn/¿·ÿÿßþ_ÿïÑÿûÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿïÿÿÿ€7777dballe-7.7/extra/bufr/pilot-gts1.bufr0000644000175000017500000000155412652630043014505 00000000000000BUFRlN€Ó Ù ÿÿ¬DZ  ÿ€„É3„A…"Ô{ÿÿÿÿÿÿÿÿÿÿÿÿýþ^û>^ǯÀð=f^1ê’Ѽm‰ÿÿÿðÿÿà@’C?ÿÿÿÿÿÿÿ¿ül?ÿÿLÿÿÿÿÿÿÿÿñ:ÿÿþy6óÿÿÿÿÿÿÿüO¿ÿÿøäîÿÿÿÿÿÿÿï¯/ÿÿà@”?ÿÿÿÿÿÿÿ«ü¿ÿÿQ@ÿÿÿÿÿÿÿþ´ðHÿÿþyNcÿÿÿÿÿÿÿûÿÁŸÿÿøåLOÿÿÿÿÿÿÿî ¯ÿÿà@•|?ÿÿÿÿÿÿÿ¾¼ÿÿWÿÿÿÿÿÿÿþÜð9ÿÿþya#ÿÿÿÿÿÿÿû¯ÁÛÿÿøå—Oÿÿÿÿÿÿÿï¯ßÿÿà@–¨?ÿÿÿÿÿÿÿ¸|ÿÿ^$ÿÿÿÿÿÿÿþõðÿÿþy}Cÿÿÿÿÿÿÿû‡Á‹ÿÿøæÏÿÿÿÿÿÿÿíÏ/ÿÿà@˜j?ÿÿÿÿÿÿÿ½|!¿ÿÿe,ÿÿÿÿÿÿÿÿ ð{ÿÿþy™cÿÿÿÿÿÿÿû×ÁÇÿÿøæxOÿÿÿÿÿÿÿðŸ _ÿÿà@š,?ÿÿÿÿÿÿÿ¾¼*¿ÿÿm`ÿÿÿÿÿÿÿÿðíÿÿþyº3ÿÿÿÿÿÿÿüOÃwÿÿøæûÿÿÿÿÿÿÿò/ÿÿà@œ„?ÿÿÿÿÿÿÿÆ<3¿ÿÿu”ÿÿÿÿÿÿÿÿð¹ÿÿþyÛÿÿÿÿÿÿÿûë¿ÿÿøç~Ïÿÿÿÿÿÿÿñ ¯ÿÿà@ž‘?ÿÿÿÿÿÿÿü-?ÿÿ}Èÿÿÿÿÿÿÿÿ'ðâÿÿþyûÓÿÿÿÿÿÿÿü‹ÃßÿÿøèÏÿÿÿÿÿÿÿò ÿÿà@ ž?ÿÿÿÿÿÿÿÆ<-?ÿÿƒ¤ÿÿÿÿÿÿÿÿð¹ÿÿþzCÿÿÿÿÿÿÿüÛÃ;ÿÿøèrÿÿÿÿÿÿÿôoÿÿà@¢?ÿÿÿÿÿÿÿÚ<ÿÿÿ‰€ÿÿÿÿÿÿÿþFð9ÿÿþz/cÿÿÿÿÿÿÿùCÀ¸ÿÿø€ÿÿÿÿÿÿÿÿÿÿÿÿÿþ7777dballe-7.7/extra/bufr/ecmwf-ship-1-11.bufr0000644000175000017500000000030612652630043015113 00000000000000BUFRÆb€  4 }ÓL Ie`Ñ(PHKL ÆLÀð €È  Å–A" A"!XPHKL -‹îšeŒ’YGÿó»¿@+V±¯çÐAðú§ÙÕ™ÿÀ Ñ£F4hÂ…F6|hÔ&Æ¥V4j±ªÔ«V¬hÑ€7777dballe-7.7/extra/bufr/interpreted-range.bufr0000644000175000017500000000030612652630043016113 00000000000000BUFRÆb€   4 }Å=€Hz°m{XDBBC Æ=…˜ €È  Å–A" A"!XDBBC C€î)ìÀrQÇÿôu>ÄðË®_ÿÿÿÿÿÁÿÿ÷¾fçÿÿÀ Ñ£F4hÂ…F6|hÒ¥F4hÑ£F—>x¨Ñ€7777dballe-7.7/extra/bufr/gts-acars1.bufr0000644000175000017500000000025212652630043014441 00000000000000BUFRªN€ÿ Ù ÿÿ«øª  &)$<€!"Ë@  g B K L % ' M*+,-)>FA!:JEU5331 ÿ´ÐÿUG7Ù&ø,žÿÿÚ>?ÿÿfÿÿÿÿÿÿóÿÿÿÿÿÿÿÿ7777dballe-7.7/extra/bufr/ecmwf-ship-1-13.bufr0000644000175000017500000000030612652630043015115 00000000000000BUFRÆb€  4 }ÓL`G\eŒBATFR24 ÆLj0F€È  Å–A" A"!XBATFR24 ‡#îšcŸòF7ÿóžDã ¬/çÐ2)@ÿÿ÷¾ÿÿÿÀ Ñ£F4hÖlÆ6|hÔ&ÆŸV4j±£F¥R¤hÑ€7777dballe-7.7/extra/bufr/ecmwf-acars1.bufr0000644000175000017500000000035612652630043014752 00000000000000BUFRîb€‘  4‘}Á'€FWÐk…dESKSFEZA î+ÔFN€=>F?    " #   )–AÉA!NESKSFEZAYTIUIERAæ†kÿü}Á'· H±¼þxßÿÿÿ¬¯ÿÿàÄ7øÑ£Fÿ4hÑ£FøÑ¿ÿÿÿÿà7777dballe-7.7/extra/bufr/db-messages1.bufr0000644000175000017500000001500212652630043014746 00000000000000BUFR2be €É–A A!øÿÿÿûëáw­ˆðŒ÷äÿþÿÿÿü6|è ê«;@ N €%ZÕk^É>ê–¥ൠ¢sFLb”<Ü  ÆŒƒÅðœáÿÿÿÿð Íˆ€Q/æ¢7ˆÿáåöAâ¼>‚qÌ>¾˜Îyc*4°Š/ÿÿÿÿÀDò…ÿüŸÿüü×ÿÿÿÿÿÿÿÿ´F² ÀkÿøùgÿÿÿÿÿÿÿÿÿÿÿÿÐÿøõWÿÿÿÿÿÿÿÿÿÿÿÿ€ÿø`ò7ÿÿÿÿÿÿÿÿµ³Bÿÿÿÿø`ð§ÿÿÿÿÿÿÿÿµYÿÿÿÿÿÿøðWÿÿÿÿÿÿÿÿÿÿÿÿµÀ?ÿø`ï·ÿÿÿÿÿÿÿÿµ³°Ñÿÿÿÿø`ì—ÿÿÿÿÿÿÿÿµï°ÿÿÿÿøë§ÿÿÿÿÿÿÿÿÿÿÿÿ¾€kÿø`àgÿÿÿÿÿÿÿÿµŸ®ÿÿÿÿø`ÖÿÿÿÿÿÿÿÿµŸ¬qÿÿÿÿøÏ×ÿÿÿÿÿÿÿÿÿÿÿÿÉÁ7ÿøÆÇÿÿÿÿÿÿÿÿÿÿÿÿÑAÿøµ—ÿÿÿÿÿÿÿÿÿÿÿÿÓÁ7ÿø±‡ÿÿÿÿÿÿÿÿÿÿÿÿ×Kÿø`“‡ÿÿÿÿÿÿÿÿ±&­¢ÿÿÿÿøŒ÷ÿÿÿÿÿÿÿÿÿÿÿÿØÁ³ÿøƒ—ÿÿÿÿÿÿÿÿÿÿÿÿÑAŸÿøz‡ÿÿÿÿÿÿÿÿÿÿÿÿÓÁ³ÿør·ÿÿÿÿÿÿÿÿÿÿÿÿÐÛÿø`f7ÿÿÿÿÿÿÿÿ­4©Lÿÿÿÿø]wÿÿÿÿÿÿÿÿÿÿÿÿÒ‚/ÿøKWÿÿÿÿÿÿÿÿÿÿÿÿÌBCÿø`Gçÿÿÿÿÿÿÿÿª§ÿÿÿÿøG—ÿÿÿÿÿÿÿÿÿÿÿÿÓÂÿø?ÇÿÿÿÿÿÿÿÿÿÿÿÿÌB/ÿø`8çÿÿÿÿÿÿÿÿ¨4¦¤ÿÿÿÿø`7ÿÿÿÿÿÿÿÿ¨¦†ÿÿÿÿø`5'ÿÿÿÿÿÿÿÿ¨R¦Âÿÿÿÿø4‡ÿÿÿÿÿÿÿÿÿÿÿÿË¿ÿø`1gÿÿÿÿÿÿÿÿ§”¦ÿÿÿÿø/×ÿÿÿÿÿÿÿÿÿÿÿÿÕÿøp.—ÿÿÿÿÿÿÿÿ§Æ¦6ÑBWÿø-WÿÿÿÿÿÿÿÿÿÿÿÿÒ‚Wÿø`,ÿÿÿÿÿÿÿÿ¨p¦àÿÿÿÿø*‡ÿÿÿÿÿÿÿÿÿÿÿÿȃÿø&ÇÿÿÿÿÿÿÿÿÿÿÿÿÍ‚Óÿø`$Gÿÿÿÿÿÿÿÿ¨f¦rÿÿÿÿøp ‡ÿÿÿÿÿÿÿÿ©¦¸ÇC$‰ÿÿÿÿÿÿÿÿþ"¢>O³^pÉ7 &¢É»ÿÿÿÿð‘<¡_ÿÿ+ÿÿG}ÿÿÿÿÿÿÿÿíom$c ÿþFÿÿÿÿÿÿÿÿÿÿÿÿâ€)ÿþFeÿÿÿÿÿÿÿÿížíGÿÿÿþEMÿÿÿÿÿÿÿÿÿÿÿÿãÀÿþDqÿÿÿÿÿÿÿÿíœmÿÿÿÿþC©ÿÿÿÿÿÿÿÿí¨íÿÿÿÿþBAÿÿÿÿÿÿÿÿÿÿÿÿé`)ÿþ@ÿÿÿÿÿÿÿÿÿÿÿÿë]ÿþ>åÿÿÿÿÿÿÿÿí…ìÖÿÿÿÿþ>1ÿÿÿÿÿÿÿÿí—l„ÿÿÿþÿÿÿÿÿÿÿûWzêÿÿÿÿ† ÿÿÿÿÿÿÿûUŸÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿú”ÿÿ Æÿÿÿÿÿÿÿÿÿÿÿø(ÿ {ÿÿÿÿÿÿÿÿÿÿÿýÿ 5ÿÿÿÿÿÿÿÿÿÿÿû4ÿÿ ïÿÿÿÿÿÿÿÿÿÿÿø?ÿ ¤ÿÿÿÿÿÿÿÿÿÿÿûèÿÿ hÿÿÿÿÿÿÿÿÿÿÿýdÿÿ ÿÿÿÿÿÿÿÿÿÿÿø ¿ÿ Üÿÿÿÿÿÿÿÿÿÿÿø´ÿÿ  ÿÿÿÿÿÿÿÿÿÿÿýPÿ ZÿÿÿÿÿÿÿÿÿÿÿøP¿ÿ ÿÿÿÿÿÿÿÿÿÿÿý¿ÿ† âÿÿÿÿÿÿÿûêéÏÿÿÿÿ Ýÿÿÿÿÿÿÿÿÿÿÿü°¿ÿíÿÿÿÿÿÿÿÿÿÿÿý( ¿ÿ±ÿÿÿÿÿÿÿÿÿÿÿü°¿ÿHÿÿÿÿÿÿÿÿÿÿÿüœÿÿÿÿÿÿÿÿÿÿÿÿütÿÿäÿÿÿÿÿÿÿÿÿÿÿü°¿ÿ…ÿÿÿÿÿÿÿÿÿÿÿüt¿ÿÿÿÿÿÿÿÿÿÿÿÿü°¿ÿšÿÿÿÿÿÿÿÿÿÿÿüL¿ÿ†ÿÿÿÿÿÿÿúÊŠ/ÿÿÿÿ–ÿÿÿÿÿÿÿÿÿÿÿüœ?ÿ†<ÿÿÿÿÿÿÿú´ ¥ÿÿÿÿÿ#ÿÿÿÿÿÿÿÿÿÿÿüL¿ÿØÿÿÿÿÿÿÿÿÿÿÿüt?ÿãÿÿÿÿÿÿÿÿÿÿÿüÿÿ†pÿÿÿÿÿÿÿú}ªn_ÿÿÿÿ†aÿÿÿÿÿÿÿú‚ roÿÿÿÿ\ÿÿÿÿÿÿÿÿÿÿÿüt/¿ÿ‡ ÿÿÿÿÿÿÿú~JkŒ8)ÿäÿÿÿÿÿÿÿÿÿÿÿü`<¿ÿ†ÚÿÿÿÿÿÿÿúŒ v/ÿÿÿÿ¨ÿÿÿÿÿÿÿÿÿÿÿü°/¿ÿ†ÿÿÿÿÿÿÿú‚ªcoÿÿÿÿ{ÿÿÿÿÿÿÿÿÿÿÿüt9ÿÿXÿÿÿÿÿÿÿÿÿÿÿüØ*¿ÿ0ÿÿÿÿÿÿÿÿÿÿÿü`.ÿ†+ÿÿÿÿÿÿÿú…Ê`Oÿÿÿÿ‡þÿÿÿÿÿÿÿú“ŠgÌt)@«ÿÿÿÿÿÿÿÿÿâ*#äû8߃ƒ ¤LŒ+¿ÿÿÿÿ Êÿÿð/ÿðöÿÿÿÿÿÿÿþÝÖ^¯ÿáÀêßÿÿÿÿÿÿÿþàÎÕÞŸÿá€ПÿÿÿÿÿÿÿþáæÔŸÿÿÿÿà@¸ßÿÿÿÿÿÿÿÿÿÿÿþUÿÿà@¡ÿÿÿÿÿÿÿÿÿÿÿþ7¯ÿà@ŠŸÿÿÿÿÿÿÿÿÿÿÿþ‚_ÿà@qŸÿÿÿÿÿÿÿÿÿÿÿþ¯ÿà@\_ÿÿÿÿÿÿÿÿÿÿÿþÿÿà@EßÿÿÿÿÿÿÿÿÿÿÿþU¯ÿà@Ÿÿÿÿÿÿÿÿÿÿÿÿþdïÿá€_ÿÿÿÿÿÿÿþØÍÿÿÿÿà@êŸÿÿÿÿÿÿÿÿÿÿÿþ–?ÿá€æßÿÿÿÿÿÿÿþØËÿÿÿÿà@ªßÿÿÿÿÿÿÿÿÿÿÿþ¯ÿဓÿÿÿÿÿÿÿþÕÞÅwÿÿÿÿà@ÿÿÿÿÿÿÿÿÿÿÿþ ÿá€xßÿÿÿÿÿÿÿþÖ~ÀŸÿÿÿÿá€_ßÿÿÿÿÿÿÿþÕR¾«ÿÿÿÿဟÿÿÿÿÿÿÿþÒÒ¹Óÿÿÿÿà@ÍŸÿÿÿÿÿÿÿÿÿÿÿþÍ _ÿá€_ÿÿÿÿÿÿÿþÉJ½“ÿÿÿÿà@m_ÿÿÿÿÿÿÿÿÿÿÿþÈ ÿá€eßÿÿÿÿÿÿÿþÇj¿›ÿÿÿÿá€`ßÿÿÿÿÿÿÿþÇBºÃÿÿÿÿà@&ÿÿÿÿÿÿÿÿÿÿÿþæ¿ÿá€"_ÿÿÿÿÿÿÿþÃ2´[ÿÿÿÿà@ÖÿÿÿÿÿÿÿÿÿÿÿþÒ¿ÿá€Ò_ÿÿÿÿÿÿÿþºê±‹ÿÿÿÿှ_ÿÿÿÿÿÿÿþ¸j³»ÿÿÿÿဟÿÿÿÿÿÿÿþ´ú±³ÿÿÿÿà@fßÿÿÿÿÿÿÿÿÿÿÿþáÿá€Tÿÿÿÿÿÿÿþ¬:¨ßÿÿÿÿà@,ÿÿÿÿÿÿÿÿÿÿÿþð ÿá€ÿÿÿÿÿÿÿþ¥Ò¡ÿÿÿÿÿà@ßÿÿÿÿÿÿÿÿÿÿÿþæ ÿà@_ÿÿÿÿÿÿÿÿÿÿÿþë¯ÿà@üŸÿÿÿÿÿÿÿÿÿÿÿþæÿá€õÿÿÿÿÿÿÿþ¤âŸkÿÿÿÿá€â_ÿÿÿÿÿÿÿþ¦ê «ÿÿÿÿà@Úßÿÿÿÿÿÿÿÿÿÿÿÿÿá€Î_ÿÿÿÿÿÿÿþ£¢œ›ÿÿÿÿà@¼ßÿÿÿÿÿÿÿÿÿÿÿÿ ïÿ်_ÿÿÿÿÿÿÿþ£òœ#ÿÿÿÿဨßÿÿÿÿÿÿÿþ¡š™Ëÿÿÿÿဥÿÿÿÿÿÿÿþ¢²šãÿÿÿÿà@£ßÿÿÿÿÿÿÿÿÿÿÿÿ/ÿလ_ÿÿÿÿÿÿÿþ¡êšÿÿÿÿà@Œÿÿÿÿÿÿÿÿÿÿÿÿ Ÿÿà@‡ÿÿÿÿÿÿÿÿÿÿÿÿ'¿ÿစßÿÿÿÿÿÿÿþ¥úœ›ÿÿð7777dballe-7.7/extra/bufr/bufr1.crex0000644000175000017500000000026412652630043013521 00000000000000CREX++ T000103 A001 D08003++ 44613 010 000 0 2004 11 30 12 00 6827 00968 ///// ///// //// // /// //// /// /// /// //// /// // // /// // // //// // // // 2809++ 7777 dballe-7.7/extra/bufr/temp-gts1.bufr0000644000175000017500000000253612652630043014324 00000000000000BUFR^ÿÿ Ù  €É4QRC_`a=…<# ßÿÿÿÿÿÿÿÿÿ¨ ‡“ìà‹‚Ö¶»¢2tˆ Ä?ÿÿÿÿÿÿÿÀ Ð ˆ Ñ*ˆ•DÿÿÿÿÿÿÐGs*ˆ•Da{];p Ð*9–Ñ*°•bÓW#UÃü/ ¨*²ˆ•h V+T¼Ð;¹Α*·¨•t£TSS¼,C|é‘*¸h•}›RƒQÜDM€- *µˆ•ˆPSO´La šPÑ*¯ˆ•ž»KÃJl`Ðw‚˜Q*¤È•²sF›EÔ|† È*H•¿;DƒC|xP½6ƒ€Q*lh•óÃ7{- PÓ  ¬ÊÑ*M–s/“%|ÄÚ ƒƒá*@ˆ– #-;#$àPò è8Q*h–Ë$sÌÐQ ¶Q)㈖Q)¥è–XC úøŒ¼‘B XÑ)›h–_K úòÈ‘G òiÑ)“–c[ZælÜQM Ó~Q)‡H–hzȼä#Qg ?…á)B薅㢲¤ì.‘|  Ä7‘(÷¨–œúúú²ý$7Ñ «IÑ(ßh–¡2ù*´=49QËF‡[Ñ'¤(–ëåʼ56ÖŠQ'xÈ–öâã*¬E6Q× Ž‘'th–ø2ââª6Ñä п‘'9è—ÊãJ—µDÒ &ˆXQ&JÈ—B*ߊ€]$TR òŠ‘%WªÝZzE0W’S c‘$|(—¤òк}5g¬í¨ˆ‹è—Xðk>T9q"e¬ëB@FRvjÿ¤ œxbòàŒ®\ó¬RñFa”¡¡Ð™ N`æRb`ÿÿÀÿÿð  ‚ ‚ ‚ ‚ ‚€@ÚüËÁøc‹ÁøKËòzMˆhYH$» ÄÏ“06|DŒ ä+°ë"iÊ•6œ©QQpmœ©QÜmœ©MÜm•ÝÆÚ V ¨¥`¦ Mâ \±ËÝ\°@±„B$B*ȵ¨#<-®s0ëÒsŒ“¡É>]’FËž,\ÂQáÌD¸à.xZe$~‡´¸<öàSdm/¹€3†–äÖC^+à‡ô–š…ák<€Â‘Ôæ[ôOYz¨Ä¾ñ?€-ÜN-¿ ^Ý}}-Ë\zØÊªÙY™×·Èx)àR7†ÖDE@2Ð<QÌ $D˜“b0QQ21eñ.£Hæ`x5)ìP*ŠÉ<Ī @H@?#˜€E°VdU´c·³²Uw%'%%×59Ô¤§ö·f¸€ˆáÂàU' ˜\„ÁEÉL¬Ë„OX(—!¼‰´©Eœ8ÀHòEÉ`ÁÒ¦“NmjsìÛ¯o Ä2EÜt6l+‡@¹`'žU+‚a$L{%ÐŽª(”;vŽ.†icX啺ŠLóx(Y@Ôc@Á#8ó†p#I÷˜Í¯±l«šÓ´¯¼üdéˆ l0eà‰&pHàR«Î¬°M‹ñ2Ê/QrhIîñIÍ0D­ `b¤áã#¢ƒ$k„—.‰U%©›Î%‰Tz>Â[;ß‹ƒ¹ÂG`pXÆiBȇò@ ’)r®wn«·¹ú§ô¶xàb¯µ$.3Yª‹Ò›@ÎÍOÐŒŠÊI'•-øm~ö€=VŽ—K©Ža4Ъf!a2 @PÀÔfP#…Êe<à•"é)\ÞÚE»mœÇ¤ÁäeN•—ÉÛ¥‡Ø«a8À$Luj׿’\¤Ñ¥b„éÓ¤N†‚1BçE0ÔáK^‘[±Í«õÃÛëõÏÁçE9›·?{žñZTšÎ”Nˆ¤ÄÆ¢²pDœµËÕ«¤Ý>„Í=òëDÍ{t}9ôh" ¹¨ˆñ!‰°ñàM1.jޱéÎ/R‰ÏÒgén±*M°díáC€†!‚ä%bH/ê»öÏNìãöæ¶làé Öów„v:ðƒGšL1,—d5•Dß±¹¥é†ÈÌWÌ!”é~(d“Úe—Ž!äîÂLƧc¹ck5ûÅÞëZ¹Y.Hu¥ Ñ\Tû-ºXUK¶›vÈL l&ÙqÇé÷xKö·I«Àitúê}ýŒžS°oË3^2C v£Å¾ãy( ¨WËÚúÚ—èí\-ÖìœùÎéfóÍi[Ÿ7Ãsü׿hׯó{·tp+ÛåÉx¯ Ì?.ĘÃ!¤*Šï±öÂHžû`äG†1V&C‰!Ø|‡q:Ãfã ×d åjùWl×:ý–Òëîù,†v«iÄè+7<½sd­æÕ j±J°Ã©ÌA„[Lß«<ß+¾JÒ«=ÅN"³ÄN¬»Ì™D˜B šв½‘Ï$L‘&J’ÊöFÀð<~¼êz¬æ(Ð "Èt>fЬ=Æ·ÁžºûI Î2Ž ó8¦ØÆ  C­1µ›G‚‚°•JÌTí™RØâ–£ì±¶†Ñ'dí#€Ahéʨ1Pqæ’ "}1)L¬ÛȪdù“ÈR§Ft`…ˆ :\x³„ËNˆé”ÈN5JÙˣΩbÕ‹¯ Àù gÉŽ€Á Í•(|ÉUF–.Dźæï¾y ð#$`„Ãmtq4ÎtPq3¤NXÕž˜©«$¾$°` !d‡udŠeuuPe¦.Y”·0Ï{ŸÂ&Xp•(áQ¢N“E)R#‹0œ‚D䔵LÕ£Æ DòŒJ⌘‡€¢"ˆ±§6ò«KI%Jܹo×Rƨ• Äò+ãHÏÌ#GoÌÅN˹Å{Ý>p¤öÅ€ö ?o³Òý4/8 KÐà „BŠ a† QÈ‚I$që¢Ûn@øî (€(@‚(¡€†`Åè$’Gº ¶ì/€ QÃŒ(†c( Žèrj¦ªË,’Ž­rÓ8( I$`¡Šac†j¨±©4ã-¸ãŠ·3µÛ†¸€àQøÄ’H Æ–8b²‹œ›n¶ã®¼«“=eÙo(Œ9`¡ iCˆ)Š&©É4ã­ºë«A€¼€`11Ña¡ññRò²²Róµƒu%Æèç(ÈY9ùÀøÎ Hd8`llPxŒŒx ˜¤˜¬¬¡É …ÕÍÚî4FÿÇ C# 2Xâ'‘!LBTMTºjÒ4ùs¯iÏ¯Ø ¸Ž @f“2\±ƒÇŽ8…3ç–¢d½K—žS¹sÀ@mÎsÎþrºÿ2Ã]´ËmrÂЫ}§e°ÐM"›qŒqä˘õÜ·n^ÅnÝ«vÍÚ´fÅqUN0@q‚D‡Ü#ãÇ—1Ëi›9~Õªöm\3b½zµJ&JXÙc#…‰^C€€„ 0‹kÙXºöÆ,5^ɫʖ°h½b”Èס6|ñ$Ì 8†tÔà… áVI1ÓEÙZÏ o‡lý¢”혨Rµj”ª•°X¡4 Ï:haBED„XÏ`h ‚  I ͉{7QYT=—×[ˆf`‰@r%Ó š€”Ødmk¤Ëå^`‚à ­×³1x×9BŒ·Ã}ÞÕ6°q^µŒÚ©Þ×›%ݺ´O³ƒú·Òháò3Ì&PP‰€L(`€Ù^# ]Ð \™£Ò2­ènºVõFôŒËæÏ<cD96>CG½:ÉFF;IÇÇ5:ÀAµº½7£#¨Ž Œ†€îR~¹¯ hÖa B7â(g™R.£H`åñze/*櫊’¤Æ±Ðšj$=9EÆÏD¹ÐMλOÎÎ4ºBF¶<À—8¡¡¨ „‰DR¦Î¯áØ0å‚„7 BÐ%¦©©b0¢È+™‡Þz±Ë…T»0#œÔ9ñøm¤FÈUWaVGàßaÈà__@ÄÏÖÂÈΣD(&/€•’nT Ó­b¸˜Ú!ChÔ>"ÃÐ2*iáj3 Ç`‡ƒ•¬ãÂÓN{œ}Øõ…uIòŽnÄQÓ]ál]TièëTéggÊK×^ËP×(˯­¸€&”¨¡œ“–T†Ò¯Âh¤îàÜ@Ÿcð3&iN0G …«³ôâVTÏ­^ÅÁ3È3ˆq^cåisaãímnáíeiÓÏZßPSØ1˺7D€2Ž3¬¨¨˜¡šU ½¹aØÃ2’Ãðè:”Ø*˜¨Æ EMÛ‹­kàáÑ|vW½à7­ÓBFà7777dballe-7.7/extra/bufr/obs2-102.1.bufr0000644000175000017500000000175612652630043014012 00000000000000BUFRîb€f  4f}Ky€EYèw+ÐLDWR îy˜‚y—F€ÉÄ–A A!€LDWR ÿÿÿþú–ózŽSø(g`£iÄa¿ÿÿÿÿÿ7ä` ¥kUÅP &褭jšÿÿü„H}µ7Rs(H ¾¥j7ÿÿñ&ÀSý=ÿþ"@_ÿÿÿÿøpBh€ ùNôh‚Ø)ÆÿþÚÂaåÎl$~gžùcÿÿú°Áasc%ÿÿÿR¨ P¶jcÿÿÿê ŠLìˆÿÿý8„\  i D5­!ÿÿÿÿóèì#÷ÿßá¤ma@øtZÿûè<  :Œ¿ÿÿÿù„Å@‘[ÿï ú.ዺ,ýô#¾ÿÿÿÿÿ¾„ˆœDw8Ÿÿ÷øs R…ÿÿÿòÿÿÿÿàh>‚g¼Lÿûü-Šÿÿÿÿÿ}@äÁãÑ[ÿÿÿÿÐÿÿÿÿþÃMŠÄ?ÿÿÿü]Ä@؉ÿø˜K ÿÿÿÿÿÁ$ÿÿÿÿå@#/ÿÿÿÿüœ „.ÿÿÿÿÿŒ°} ‡¼°Óÿò – ÜÿÿÿÿþDÿÿÿÿÿÉÂÐ.à_ÿÿÿÿùØP’‹Ïÿÿÿÿð¯™àïÿæÀðÈ/ÿÿÿÿüØKJ‚„ßÿÿÿøEà¿ÿÿÿÿô ŒÑ9¢ÿþŠ€æÿÿÿÿÿÍ‚¨`_ÿÿÿÿûnX€´|ÿ?ÿ^`Jžß×ÿÿÿþÀBô\ÿÿÿÿÀÈ@c—?ÿªÀA ï»ÿÿÿÿÄÿÿÿÿþ¨$@V†3a>ÏÿÕˆ=àÀ ÀÀ áà@çp8C‡páÀá8áÀÄp ÄhÑ£FbÄhÑ£F4¸Ñ£F4hÒãF”iQ£F.4hÑ¥Æ4¸Ñ£R*4hÑ¥Æ5(Ò£F\hÑ£K4iq£F.4hÑ©F•4hÒãFJ4¨Ñ£O4hÒãF>4hÑ£R*4hÒãFJ4¨Ñ£K4¸Ñ£R*4hÒãF.4hÒãF.4hÔ£J4¸Ñ£K4¸Ñ£K5(Ò£F.4hÒãF.4hÒãFJ4¨Ñ£K4¸Ñ£K5(Ò£F.4hÒãFJ4¨Ñ£K4¸Ñ£R*4hÒãF.4hÓãF07777dballe-7.7/extra/bufr/bufr10000644000175000017500000000027112652630043012557 00000000000000BUFR¶b€  4}Ky€H[%xÀ€€44613 ¶y‰¾yˆlF€È–A ÉA !LW"‚€õ-æ÷M(cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëäˆ4hÑ£F5›1£F4hÑ£F4hÑ£F7777¨ dballe-7.7/extra/bufr/ed2radar.bufr0000644000175000017500000001341612652630043014166 00000000000000BUFRÿÿ  <€ÁÁ Á ÁÁÁÁ!!!Í Á  ÕÁÉÁÂÇÈÃÄ´ H>¼'š†¥µ K~hL–öЙ(è@“¬ÿXµjÕË—/^½{ ±bÉ“&lÙ´hÑ£V­[6lÝ»w9rå˧N»vñãǯ^¾|ùû÷ïà@ P¡C‡$H‘"Å‹4hñãÈ‘"L™2eJ•.\¹“&M›6téÓçÏŸB… 4hÒ¥J:u*T©V­ZÕ«W¯^Å‹lÙ³jÕ«víܹríÛ·¯^¿~ýü0aÇ,XñãÉ“&L¹ræÍ›>|ú4hÓ§NZµkׯfÍ›víÝ»výû÷ðáÃ<¹rçÏŸN:uë×·nÝû÷ñãÇŸ>|úõëß¿>3]ß’FO€3b ÿþþ ÿà?àÿþþ` ÿà?àÿþþ  `àà Ýþ@ÀîÝþà`@ ?à1 Àt`vÀU`•`SÀ-``®à@ à Éþ¬ÆÈÞz ‹p \ W)¨ Éþ €  àà\@]`½àW¶€€S @O ó`°ï`Ø `[`Z`Z@:`W`` à¹þ&¼ Ò¾¦`> @\l êÔ´N¹þ` ` ?àÀWÀ7 À{ ›@Z€Y`– µ U1 Rà´š[|À`]@^ ]@Vu @ ?à­þ4oz¨¼Ê¼ Ò²„ DPZqŠœ°ÆÌfò¨ ­þ¡` ŸàNy`^@__ÀYÝ @Ü YÀ5 `Õ`QÀtÀUà V`7@x RÀ/ o /@ à £þ6Ô¬ü–²h 6<¸Êîð$£þà   ÿà L XÀ?À8À@úà¶ÀU @R M IN@‹€ `L € ÿà  ›þBDÎü Öt² ~j<âL™þ `à à`L W€Z€Wàw`4à`X ¹ ·ÀU– €T@NÀ@ _à$ ‘þP:ZB@.D N L L\‘þ`@€ÿà@MÀ“à-T@U`¶ ´`O@J@ßà(‹þfH N 4¨h‰þ  àààP`²`mÀ à,ƒþüƒþà `à ÿà0}þ}þ `ŸàŸà4wþwþ` `_à ?à8qþ qþ  `ÿà@ÿà<kþ,kþà `ŸàŸà@gþ4gþ `_à ?àDaþ@aþ` `ÿà@ÿàH]þH]þ  `¿àÀ¿àLYþPYþà `à@àPUþXUþ `?àÀ?àTQþ`Qþ` `ÿà@ÿàXMþhMþ  `¿àÀ¿à\IþpIþà `à@à`GþvEþ `_à ?àdCþ|Cþ` `ààh?þ„?þ  `ÿà`ßàl=þˆ=þà `¿àÀ¿àp9þ9þ `Ÿà àt7þ”7þ` `_à€_àx5þš3þ  `?àÀ?à|1þ 1þà `à ÿà€/þ¤/þ `ßà€ßà„-þ¨-þ` `¿àÀ¿àˆ+þ®)þ  `ŸàŸàŒ)þ²'þà `à@à'þ¶%þ `_à€_à”%þº#þ ` `?àÀ?à˜#þ¾!þ   `ààœ!þÀ!þ à `ÿà@ÿà þÄþ `ÿà`ßà¤þÈþ ` `ßà ¿à¨þÌþ   `¿àÀ¿à¬þÎþ à@@Ÿà `-@@€Ÿà° þÆòþ `Ÿà à´þÔþ ` `à@à¸þÖþ   `_à€_༠þ ÔÊþ à@`_à€O€-à@  _àÀþÚþ `?àÀ?àÄþÜþ `@@?à`Lr@ ?àÈþ^C˜qÙ+ƒänþ  @@àà2šÚ]ü_Ý@àÌþ^ËÓýùÛÅýÐànþ à€@ààxý  _À=  _Àw•/`@ÀàÐþ\!½Òü Ïý×wzönþ `@àÀw½ _Á¼]xWµsÑ@@ÀÿàÔþ^)ƒÚüË­¿y{Wlþ `@@ÿàšÞ{šÙ—ut‘±@€àNÀ ÿàØ þ`§Íçù­˜d E.ÞÈnxìêþ  `€ÿàW [€zzÙ V@Trà TÀL` ÿàÜþbQg¡Ÿ™“}yM1A j þ à`@ÿà€S WÁ6ÕuT2ñ1@@ßàà þj1k}{mWUC5?IO>ÐÎ` þ `@ßàÀò–Õµtt4ÔUóñM¤€ Oíà@ ßàä þn7[GE=MEQA?ä¾h–ò þ``@ßà“tóS TÁU’1NKà@Àßàè þp.4=A3/-#æÐb ¤¨Bð þ €@ßàБ’QtÓRòÒ1ÐÎn  %`  % @Àßàì þpû+A=5-üâäÄÖÚ@FÎz¨| Ü þàÀ@ßà nNp`O´ÓQñ‘ONŽN N M @ À  ¤È)« `Bä`@@A@'À@€ßàð þf-/= %'úôæäàÔâÚÚÈÐ@ºHLÆLLZH>B®`žä þ à@ßà`ÑòóÑPrQ°°11ŽîN®íMÍ­ @ @­ +  àk € J@¤%eÈì@ E@‰†  €&`@@¿àô þf-/7 %ûòäÎ¤ÈÆÔÐÄÚÐÒº ž$fœj”rXt~„ZnhF p8 €à þa@@ßà`2óqP’Q/o.î@ `(` €+@@KÀl Ë  @IÀ@Ià@C, €G` ‡)mˆèÊ)é E%£` @& @(@¿àø  þf ðâè° ðà"œ4(bv phJ€df^î|~Žˆ¦Ì†TdŽFzÖ þ À@ßà€cÍî  )À @æ@ÀGl )Ë«ˆLˆ‡E„A@ €$` @' @ `¿àü  þz°ÆNd´1(VpjTvØœ¶¼À¯ª€ØtŽrä þà`@ßà Àf@ @ àŠÄêÉL«î‹JLã¨à' @ ¿à þØ–J&¨¤PVp¢¨µÔØ€j¢¾ zâ þ  @ßà  (À à$   éåEÇ«ËJ«ÈiMéHà `'€@ à¿à þÊŒ p *J.d–¶¤–n†xŽÖâ¢.Ü þ`€@ßà €G`  %!$&舭h…Ɔ¥£`   $@ `¿à  þ̾ r LN”NbÂvt|†*€7777dballe-7.7/extra/bufr/obs3-3.1.bufr0000644000175000017500000003405012652630043013644 00000000000000BUFR8(þ  ´ÀÊ 80?€€þ € ÀI$’I$’I$’I%$’I$’I$’I$’m¶Ûm¶Ûm¶Ûm¶ä’I$’I$’I$’Km¶Ûm¶Ûm¶Ûm´PC!Lt%Kc\øFS¥m|g[ç@ …1Е-sáN•µñoD2ÇBT¶5Ï„e:Vׯu¾tÈS RØ×>”é[_ÖùÐC!Lt%Kc\øFS¥m|g[ç@ …1Е-sáN•µñoðN@ €@ €@ €@ €@ €@ €@ €@ €@ €@ €@ €@H€$Áªªªªªªª„Ì œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@œ@ÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÀÚÁAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁWÁ–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–A–@óTž_™‰J"^À3Ygž}ÂH¨êIÑÊpøTŽV¬VµŸÃ®Ù½…Zì_htë_½[Ý‚åâ—f‘¼ìÝôñP/ƒÔ1†b—"p*އàŒj$duÕ+ •4N=ž}l´@¤x6Iª>ÐV'êшW†jÃÑöZI´©=³ÚΓt/»¾GÞØýã˜'bBî®$,‘yoÀlqúM–$æ1ÕÓP4º¹&¹ý<9zQÝ‚˜÷õZªØ•gékÃgbë0Úv6ÛA÷º­ãQ€EÌÖáèï`øè(H±†M¸²}«§ø¨BÈ~RèSâœm,ýwh©ãJË*IU.’²›Úè0óµ˜í@9mñŽ¢]ló7Ö@ž`±WŒÃLƒÅdü¿-îù‘¯ÌÍŒ'ò"ïý"©!aEŠw‰4&¤5­7ÿ*f§XæHØPtË&6œW¶ð5Ǫ½4yã#îØ`u7 ¥xJÆëÆGJ’¶–™[ ä>ç±ß>‘ Ã;ŒìD”eו7ôkQPº–Êu«/Qm{¬5d²»Hã[Zã9÷\(¼ï5÷ØðAÕ†*ÜRocž %LYlüÍq&zæôBg¤r½'ªÐP6¥ÄÙå M[C‘0—ÞÁOÁÂÝm†3Á U¶„æ<¾Œ€ùù3²AµÄÄ7  ;¹,ÓP^´ÈT±¨…3…´G€öP ‡¢vøJp|¡Ùqb®ÃkFØÆ úÎB—/V™Ö!Ã\K^¥íi• Û– áòô?¯À‡+!ò^Ö¥ ¡ùŠ ¤A§Nˆ(ÐXðÀaÃvb¶!\FÄû6(¾R.¥ãO&¥Ý\êáv-\?½{‡4 à!0SÀÈAÏ ü+ˆ^0ÊÁ²Ã¡‡¿z‚%ª8T¨©ÐT¬)^ŽÌ¼Kј~À@ (/l󂄨 .$/èg`Þ“rç,ÎòŸ3A>ˆÍÚ_õ jÃW$²1mîó~!`!€yÔ `2Ðrá‚7Ü œ2 Ñi´sŽçpϘ ÉE*’…8*5¥ìQÛ(¼™ˆÍú1Fš —ª‹£ Õ8nËÝÂÑTy'Ì3¥MÕö%µyay>´rÿîT›h*R¤¬Ì0׸ŽËØÿÂQ,o%K³ MVEÃ~ã™þÏÊùÃùbmŸèúx«-Ì+4×8N«ÐýÁ±g#Ës… OW¥ç‹g»gJ*剪z¢)bˆ­. #0շ΋ÆûA0ìc#K³­UY7f)¡ïP¸CFQ΀£I‚Œ­-Ì (Ó·.c¾ùÀðìg%Ì´ AaÝxÖ¦BáP¦¹Þƒ#‰‚ˆ«­KëÑ6ÎK¼ùÁ1 w+ÎÔÕ…xåaáçÛȸ“séÍګá/w_Y¿‡€¿æÌ0~q;âýÇ›&nXLÉùÌôé]Õm±;q·pÔíçÜE¹mt’ì}ß›Ì7²o™_œÀã^< dÙÞ)]#¢<²+Ê$^_…ÒH_qs…œHâÓ R±03Ö‹´"dm1KBäø4¡ÂMP “ÍÞy• SekãBŠò ·J B†6#ªáë!>Õtµ: «ÑáE 2ÐÇÀÐ @U,!ú©mÞö_A”UnÁýÈm"«"8¸ïU[Zm2C-È¢ˆT!Ck Xà.[È? qÂQ€†|/¡^×µ!ñ‘‚S.£ÔÐ q†  @¸À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `Àuqv¥I>ø°âm ê%h—â?‰è!¡x1 Œˆ¿¥Ö2 P¯Åš.‘ù)Æ©Žn•ra!7D¡‹Ú)¸ÈsÌ*ºaÔhÂê°ÖB4™²Š-j©R)71‚ÎÚa ä*U Ñ8†¤—T°ÒB¯ ’%Ð`Á´‹:&X<@?ˆôÉ3¶r¯Æ pŒKT$¼@²ÃŽÊ=tã[QVy Í…Ü)8šý°èaÁâê@G~¼ '”—jhEÜ Î?)Ä%Ñ(“É›ˆÆ RhÖª t hpCžx-€~WCî2Ð<®·ãI©³Õ»äeùŒ_ñ–ŸŠœ™ÿ¤,‹.š‚!‡bhD £‚ КNßj‚j Vjž¯B§ô“1öFë#À…cÀ @€p€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€RŒÕò-ÕB(é3ÙQ æI"Bpw‚X5ÔŠÁ\‘]á§¹ÉP‹ÕÔ($á ›X+?XÁ%9¦4Ð…­/ ,‡òIÂŒ‹¸`'L«”ÜÒ$: `ê¶HB1—èÃäÃ(i_..Z«5—¤3ÌDµ(ÖIÄA ­x: †bÃÿ]^^W'Ä¿Êhj+…˜Òv(;U|mzeÊ¡ÎìSBj¸Nþ¸Ôƒ< ÐIœÐ}j6]ºò\1 Ê.nrî€îÆk¹½©Éú:Z P?Ñ— ´CÙ ÀCR@‘¨êTzbØLÃǺÍïy{ÀÛ„íÆy£@Ȇ% ðì2A X €G )ÉÁÂõŒ8i%·R‹Sšû—ʽùïÏ%|Xµ°a¨ÃP®0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À00‰T Qà?‡ßãŠvL©œ(Cg/¤Ž?S# ¤¹!äX“ðð£´zQ¸9§LÎô{˘ãkb>µœI ÓRˆ}¦D>TGP`„¼æžô2n ±Ô.e½#,¦ŒÀ"¼Kˆý£ÀN‡CÔá ‘Të '+Å4µÔb4d,3sˆx ÙŽ/%x¤’2<Ø«bXcæ|x  1Éqr®Å®ŽM' Ðkf 5jÀ0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À×’Ä)6>I‘z³Gñ_ô#‡±:ÇYƒ ¢äˆ–Aõ¾GXÛXÚ©?%lbA KÏ2pZ¬9Ã:·ïâ¬UˆQVSÎiÍ#£C÷~ïõÒ¶Æt¯)nÀHs¼—›%mNë@ˆiâ3=XX™Ízà(*†a˜¦†^GQ½k™uÅ;R”¥I3ᬩ=‘ÅexkÇéú~¡˜†!ˆaeÜ|ÛÖ™—ZT¤q3I@%Ƀ#RXvñÌxá&‹âˆF€_'ÄkWõEAHÒ4 Bш˜?%ùi^¨ñ|bx¾/‚ æpÜ6•ŽV$ô?À|MÊ#3XWùä|߸jŠb(ió„Ÿ7q¾b),CNsøþ ÅaÐÁ;ÒUiiÝWÒ„¢˜Š"†¢(-ô~ÚvAyRÑÓ€ç=ÎÀ6€€ 5 àÀ0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `¾i zb7,UmsÒô€¾ŸOH 6ô€½ÐØ<~KJ®B¡±9`ú¢c9\¯x¿b¨‰ï {¿^09¥‚$‡…E´òÁªíz@ È”%+†C$±ˆJôz@%sÙ¸´N?% •«6éû ŠÃä3ItºC(ŠÆá/×ëÁ¼ð‡Î£br1`°‰S³nX|&E@‘K¦’éu]„ÃÝoÃaï.‡“ s* hÓx¼b)tÖE5ÍeYtZ! {·ÚlËö ÌvÀÃP† \`À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `X> l¤lÀlÀlôˆ¤¤Àˆ‰(ÙÙ•E•²¢nŠÚŠ Ḭ̀||`ÌÍ98é±Uéé¾õÚFb²–°Ä©L¨üÅMüÅdýM0Å11Míîuº ªv )}aÙ`õE)}a)E}}Ía•••±a~ÎRnR¾¼õyya)EEa±yyÉ•a•±Éa±É•yaÊ9ÉÊRn½ÁÁUU9qU9õqÁ¥Ù¥Á¥ÁÙÁÙÙÚ}ÁÂ.~P ˜í€†  @¸À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À±úBÉh1™i˜ii0É0iÉɘ™j2úb2bÊÚªx¨@áyA¨@àáxy©Ùy©zzÚª©BBÛAQºé!‰Q¸‰QQ!Q‰P¸é‰¹QººRRºR„RZðùYY)YÀùYññ‘ZYñ)òÁÁ“‰óZ*Z+"S‚±Q!±‚Q!°¹S!²‚SêIêRR³:8Ú;Ñq ¡ÑÙÑ¢Ñr::¢:¢j£:ÒÒ¡r£œÀ1Û @€p€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€iȘ+mb•.šÈÄñx€J3Š…D˜à‚ —Iäò¡ÐÖgF9" År¤âU&Èãè˜ 4ˆƒñY0¼cRÇÑy6®f™©ÊTÖA'ŒÇƒ€à€$£1™ž‚AŠucF a©ÓÇD¼Ì<‰EÃÀ¤.D¦²)ôú§3)Ò 7ûi†ÇLžFòÜ’‘FäRI8\X’KÓyÌðJ-cpDÂaV2•Ë„‘±\œ6 ÁòqH®R0Æ£qáhìœf;`a¨ÃP®0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0.§”ð;+:“–ÄÑlW‘…yã°Þã B‘Bi ˆÊ^¢6®Ë'IYDÄðæHâDcÐØ6 ä@ôY™z€£¬I ¶É²B‚šf)|PŽáð¶"(¦8 c¹BFeñ {H*z”2OÃ8§)Ç’:N”„±:N"xÊ6B°Ê6 ¤±d@’ÅѬ|šËËú¶ªRNz•‘>Œ!xÞ>†Ãxì4 c°Š>¥Àbæ‘ê·4íKR­¦%ɸgà r2ãÈ€Q…cX*Œ„pÈ.’§Ádq£Š£©@ÌvÀÃP† \`À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `a–*{p…tûJc8×&E¡hQ …DH †1h‡$“]-½É“ã‡y—6Ñ´¥'±À: ‰10(D1T ÎÒÜä;R³ÙO_éÙÜwÄíJOÓwqÜA"D¡‰È’$¬/‹ã@ýWÐö”%Gé³ZÍ3ÜÊ'Œ|ž)ÄÑ V2Œ¡|D Êrä¹)ÒE­>_`9º`mšÔy0/4à&Ó8ÅhkÆ1 ¡/DU0WX¥½õšbw¡†D•@ èz Éà_, ’ •7¡|Ó;ŽäµHZÞ‰v ˜í€†  @¸À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `À0€ `ÀËØTK0éZ¬˜€ ñÐqjQzd“&ánk&&yVIŸHû|±ÿþò…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿêSÿ€èÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿþ"i`(}ý¦ÀÆé“`{ÿÿ~ÿßÿÿÿÿÿÿþÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿtÀ\©±´62¹»´³/¾bŒä@zBtàIÀO÷AÄ ?ÿÿÿÿøCY X¾?ÿòXÿÿÿÿþïÿï(PÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸþ¥?ø~ÿÿÿÿÿÿÿÿÿàéÿïéÿÿÿâ'ö‘7ßÚX®™ÿÿ÷èÿýÿàj¿ÿÿÿàÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿ@ÿÿ÷LAº3+Ck “qûæ(ÀnD3$q `ûà­´A#ÿÿÿÿÿ€d5嵺^ÿÿ2ÿÿÿÿÿÿã?óÿÿ€‚?œ`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ýJðýÿÿÿÿÿÿÿÿÿÀ2Ò?ÿßÒ?ÿÿÿÄOí,¿¿´°2X ¿ÿïÑÿûÿÿÿÿÿÿÿÀ?ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿþ€ÿÿî˜ ‰4†Ö'W&rÔgV†Ç6'VWGFVÅ÷ÌQ€Û*·Hy†Áj ¨=ƒÿÿÿÿÿÈk?kÁÿþ]ÏÿÿÿÿÿÌŽAE ‡`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþú”ÿàú?ÿÿÿÿÿÿÿÿÿ€d?¤ÿ¿¤ÿÿÿˆŸÚljºe¿ÿߣÿ÷ÿ®ÿÿÿ€ÿûôÿÿÿÿÿÿÿÿÿÿÿÿü?ÿÿÝ0@Jlmì®M-Ä¶\¸’P{‚>“òPa ÿÿÿÿþÖ~ÕçÿünŸÿÿÿÿÿŒÿÂÿþþ@?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþdÕ©ÿÀôÿÿÿÿÿÿÿÿÿÈHÿÿHÿÿÿÿ?´Ø >þÒÀ@tÊ 9ÿÿ¿Gÿïÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿÿÿÿø ÿÿº`$€ .Ü™ZYœÝØ[ß1Fo)'Úøh n/ÿÿÿÿü!®¬FçÿùE?ÿÿÿÿÿ8„ ( ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿ¨ ÿ€èÿÿÿïúÿÿþþÿþþÿÿÿþ"jPýý©@lé–€\ÿÿ~ÿßÿÿÿÿÿÿþÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿtÀ<d"¶²2·¾bŒÖWÂ;`lÈP¯B¬ ?ÿÿÿÿøC`‹^]ÿÿô!ÿÿÿÿþïÿï(PÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸþ¥?ø~ÿÿÿÿÿÿÿÿÿàéÿïéÿÿÿâ'ö‘—ßÚDî™,ÿ÷èÿýÿÿÿÿÿÿÿàÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿ@€ÿÿ÷L`G“+k+qûæ(Àm"a¤­`ü~¥ 4(Acÿÿÿÿÿ€d5൪]ÿÿN'ÿÿÿÿÿé‡0Èú…‚d@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ýJðýÿÿÿÿÿÿÿÿÿÀ2Ò?ÿßÒ?ÿÿÿÄOí,Ÿ¿´Ø Ý2l ßÿïÑÿûÿÿÿÿÿÿÿÀ?ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿþ€ÿÿî˜`äæWW'W–â÷ÌQ€Ú ÃIŒÔB#)ù¨„ÿÿÿÿÿÈkßk_·ÿþAÿÿÿÿÿòá3ÿÿ? /ád8ü5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿÿûÿ€èÿÿÿïúÿÿþþÿþþÿÿÿþ"j}ý©@vé” <ÿÿ~ÿßÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿð¿ÿÿ^ÿÿ€ÿÿ•$†ææ÷fW"÷ÌQ€Ùb*H[<8Á*hM…ÿÿÿÿÿÈk]jÚ·ÿþœOÿÿÿÿÿåŽÁž5 † àÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþú”ÿàú?ÿÿÿÿÿÿÿÿÿ€d?¤ÿ¿¤ÿÿÿˆŸÚDÿiºeÿߣÿ÷ÿÿÿÿÿÿÿ€ÿûôÿÿÿÿÿÿÿÿÿÿÿÿü?ÿÿÝ0@-)¬,쌬N®Lä±©è’*y„¦^SâP_ ÿÿÿÿþ×ÒÖßsÿü’ßÿÿÿÿÿäÿÂ'ÿþ þ˜ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒïû¿ø~ÿÿþÿ ÿÿàéÿïéÿÿÿâ'ö¥ßÚ” Ι,ïÿ÷èÿýÿÿÿÿÿÿÿàÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿ@€ÿÿ÷LLJcKs#+s+“9ûæ(Àl¥j¡7@tñ´@cÿÿÿÿÿ€d5̵£ÞÿÿGÿÿÿÿÿùp¥¾‚ã ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_ôÂðýÿÿýÿ@ÿÿÿÀ2Ò?ÿßÒ?ÿÿÿÄOìúï¿´ 1à_ÿïÑÿûÿÿÿÿÿÿÿÀ?ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿþ€ÿÿî˜@™GVW76VÆF÷&b÷ÌQ€×™»G? B!Áj¨v‚GÿÿÿÿÿÈkýkF±ÿþÚÏÿÿÿÿÿÙ2e H ÂPÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿRŸü?Gÿÿÿÿÿÿÿÿÿð ‡ô€ÿ÷ô€ÿÿÿñûH€{ïí"wL›×ÿûôþÿÿÿÿÿÿÿðÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿ€ ÿÿû¦8§U1•¥Á饜½!…±±”€€€€€€}ó`5óýÒUY ¥ðS®wÚ àSÿÿÿÿÿÀ2íÚÞ0ÿ’Ãÿÿÿÿÿüƒ¸@—ßQÂN8Iÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø]ÿNwÿÑÿÿÿßôÿÿü!ý ÿýý ÿÿÿüDþÓ`4ûûKMÓ#Íÿþýÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿߣÿÿÿÿÿÿÿÿÿÿÿÿÿàÿÿþ逈)èDresden-Klotzsche _|Å uÄž•(0ü´œ‚8ÿÿÿÿ𠆵6°Ëÿÿãèÿÿÿÿÿÿ î å÷À PpnŽ€?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþDÓ™ÿÀôÿÿ÷ýÿÿÿÈHÿÿHÿÿÿÿ?´ þþÏ 7tÈp5ÿ¿Gÿïÿmÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿº`"€ ~“Y\˜\™ËP˜\ÙZ[\ˆß1FX°¹#øI¬¦¡Öÿÿÿÿü!«½©Ïÿú|¿ÿÿÿÿÿÿˆÿüü@€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÈÿ±ƒÿ€èÿÿÿïúÿÿþþÿþþÿÿÿþ"jð}ý­ é•àaÿÿ~ÿßÿÿÿÿÿÿþÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿtÀC&²´·4·3²·¾bŒ³Õ¢Dü!4§L1BT ÿÿÿÿøCXkRoÿùBÿÿÿÿÿ_ÿ¿ÿø-ø… ÿ@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ>?ì`ÿàú?ÿÿûþ€ ÿÿÿ€d?¤ÿ¿¤ÿÿÿˆŸÚ€ßjP.:e(?ÿߣÿ÷ÿÿÿÿÿÿÿ€ÿûôÿÿÿÿÿÿÿÿÿÿÿÿü?ÿÿÝ0ÀO¨ÎL-ÍlήN…é¬--Ä «STÔ›áBv3ïÐÅÿÿÿÿþØ^ÕM3ÿýôÿÿÿÿÿCœÊÀ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿõ)ÿÀôÿÿ÷ýÿÿÿÈHÿÿHÿÿÿÿ?µ( þþÔ Mtɰ1ÿ¿Gÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿº` € «RÙˆß1FXeá$Ǖىq%~ åý?ÿÿÿÿü!ª}©*÷ÿùdÿÿÿÿÿÉÿ‚¿ÿü ü„ÿ„ ãðšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõ‹þÆþ£ÿÿÿ¿è_ÿÿøCú@ÿûú@ÿÿÿø‰ý¡ÀA÷ö‚‹¦Agÿýú?ÿÿÿÿÿÿÿøÿÿ¿GÿÿÿÿÿÿÿÿÿÿÿÿÿÀ`ÿÿýÓÜUĦèêèèÎÂäèZŠÆÐèÊäÈÒÜξùŠ0sãéÛˆxx=Ù3õ ¯Ùÿÿÿÿÿà tmE³?ÿîáÿÿÿÿÿýÜ<Çï€@Áä'W€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü*ÿ¦ÿ€èÿÿÿïúÿÿþþÿþþÿÿÿþ"i}ý¥€¢é’ Qÿÿ~ÿßÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿtÀ9}§:²¹712¹3/¾bŒ¦ëG ªäM}BSø_ÿÿÿÿøC\ËS%ÿõÜÿÿÿÿÿ`w ³{à$@U Æ@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ?éÄÿàú?ÿÿûþ€ÿÿÿ€d?¤ÿ¿¤ÿÿÿˆŸÚŸh #:d`ÿÿߣÿ÷ÿÿÿÿÿÿÿ€ÿûôÿÿÿÿÿÿÿÿÿÿÿÿü?ÿÿÝ0ÀbŠnŽL.¬M-Ìä§«’éUSµSDЖýÿÿÿÿþÕŽÓÕWÿý“ßÿÿÿÿÿ€ûÿûÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿ©Oþ£ÿÿÿÿÿÿÿÿÿøCú@ÿûú@ÿÿÿø‰ýŸ@-÷ö‚¦Aûÿýú?ÿÿÿÿÿÿÿøÿÿ¿GÿÿÿÿÿÿÿÿÿÿÿÿÿÀ`ÿÿýÓœV¨‚êÎæÄêäÎ@@@@@@@@@@@@>ùŠ0g iÕȆ˜D0U /Ðÿÿÿÿÿà emE4ÿÿуÿÿÿÿÿýü"ÿà`—á'üFÿŠÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸö.ðýÿÿýÿ@ÿÿÿÀ2Ò?ÿßÒ?ÿÿÿÄOìúO¿´ Ý2ÿÿïÑÿûÿÿÿÿÿÿÿÀ?ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿþ€ÿÿî˜@»$¶V×FVâ÷ÌQ€Ò&&H›be‚°ÙA¨e~GÿÿÿÿÿÈjYi¹³ÿþ¯ÿÿÿÿÿëÿá‡ÿÿÿ A?â ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæGýŠŸü?Gÿÿÿпÿÿð ‡ô€ÿ÷ô€ÿÿÿñû€3ïìxLU¿ÿûôþÿÿÿÿÿÿÿðÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿ€ Àÿÿû¦ˆ7777BUFR®Nߟ€ÇV±ACAÂ8C!):=AÂAÂC6 Z  *D *O    CK6?íª£)""ªª)¡¤"!*¡¤*¾bŒà Ò<EÿÿÿÿÐBt?ÿÿÿÿÿÿûfËaÏÿÿñôÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ûÿ¿Gÿðÿÿÿÿÿÿÿÿÿÿïéÿïéÿÿÿâ'ö–ßÛÿÿî™ÿÿÿÿ÷èÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀ€ÿÿÿÿÿðAbb*ªB¢¢ª’iZJ*aûæ(Àn>¨$J ÿÿÿýÔÀãÿÿÿÿÿÿÿµÇµ•ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿ¿ûô÷ÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿþ"hp#}ý¿ÿþéŸÿÿÿÿ~ÿßÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿüxÿÿÿÿÿÿ%´²¶¤7¶:2·0º¾bŒâgZDEx®\P!A¤?ÿÿÿÿøCY X&/ÿóâÿÿÿÿÿþïÿï(PÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸþ¥?ø~ÿÿÿÿÿÿÿÿÿàéÿïéÿÿÿâ'ö‚çßÚ0n™ÿ÷èÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿ@€ÿÿ÷L`BÚ “[{s ûæ(Àna¦$å!@Š ûô Bÿÿÿÿÿ€d5ǵ°áÿÿ8÷ÿÿÿÿÿã?ðqÿÿ€‚?ƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ýJðýÿÿÿÿÿÿÿÿÿÀ2Ò?ÿßÒ?ÿÿÿÄOí@/¿´Ø]2” ¿ÿïÑÿûÿÿÿÿÿÿÿÀ?ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿþ€ÿÿî˜À‡æ÷&FW&æW’÷ÌQ€ÛIžGdŽÁÊhU€ÇÿÿÿÿÿÈll·ÿþ1ŸÿÿÿÿÿÀ}ÿýå ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿù¹ÿV§ÿÑÿÿÿÿÿÿÿÿÿü!ý ÿýý ÿÿÿüDþÓ`MûûMmÓ(Áÿþýÿ¿ÿÿÿÿÿÿüÿÿߣÿÿÿÿÿÿÿÿÿÿÿÿÿà0ÿÿþ逦(ƒCuxhaven |Å ¸{TÄØ¤ â„x$ÿÿÿÿð †Æ¶¾«ÿç`ÿÿÿÿÿüßÿÞP ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ýJðýÿÿÿÿÿÿÿÿÿÀ2Ò?ÿßÒ?ÿÿÿÄOí"¯¿´ˆ2X ŸÿïÑÿûÿÿÿÿÿÿÿÀ?ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿþ€ÿÿî˜àŠ¥&÷7Fö6²Õv&æV×VVæFR÷ÌQ€ÜcIEÝAù ($…ÿÿÿÿÿÈkÁkw¿ÿþ>ÿÿÿÿÿÆŽ ê H@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþú”ÿàú?ÿÿÿÿÿÿÿÿÿ€d?¤ÿ¿¤ÿÿÿˆŸÚl _i°,ºeÿÿߣÿ÷ÿÿÿÿÿÿÿ€ÿûôÿÿÿÿÿÿÿÿÿÿÿÿü?ÿÿÝ0©Ž¬¬m îä´Q*‘Ó…„‚ ”Ðmÿÿÿÿþ×ÕçgÿýÿÿÿÿÿŒÿ¯ÿþþ€?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþdØ=ÿÀôÿÿ÷ýÿÿÿÈHÿÿHÿÿÿÿ?µ(þþÔ 6tÊ7ÿ¿Gÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿÿÿÿø ÿÿº` € BX\›š]ˆß1FjÅ$Ýk eÂg¸ šÿÿÿÿü!®e¬×ÿùõ¿ÿÿÿÿÿ¯ÿ„ïÿüü'ÿ…Ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ™öðýÿÿýÿ@ÿÿÿÀ2Ò?ÿßÒ?ÿÿÿÄOíTÏ¿µP]2Ð ÿïÑÿûÿÿÿÿÿÿÿÀ?ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿþ€ÿÿî˜`Åv&Vâ„×VW&—G¢’÷ÌQ€ÚþZI~ûNÁ"Ùòè†ÿÿÿÿÿÈk­k ³ÿþ”¯ÿÿÿÿÿòá/ÿÿ¿ GápÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæGýƒßü?Gÿÿÿпÿÿð ‡ô€ÿ÷ô€ÿÿÿñûPkïí@·L¯oÿûôþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿ€ À=ÿÿúíÿÿüÿÿÿtÀ)‘ ·3²¹6º²·22/¾bŒÑýÂP4¼åO“@|?ÿÿÿÿøC\{ZUÿÿñÿÿÿÿÿw±ûà.0…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøUÿL'ÿÑÿÿÿßô/ÿÿü!ý ÿýý ÿÿÿüDþÐ@ûûAÓ!Àqÿþýÿ¿ÿÿÿÿÿÿüÿÿߣÿÿÿÿÿÿÿÿÿÿÿÿÿàÿÿþé€N);Muenster/Osnabrueck _|Å Žy›´"ü­ Š†X(ÿÿÿÿ𠆺6¯Ë?ÿéÄÿÿÿÿÿþÀî&÷À H€˜Œ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿõ)ÿÀôÿÿÿÿÿÿÿÿÿÈHÿÿHÿÿÿÿ?´`þþÐà tÉ`$ÿ¿Gÿïÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿº` ^ÔÝÙ[Hß1FeÅ&–ï eá'› b ÿÿÿÿü!®Ý®[ÿø¯?ÿÿÿÿÿÈ;ƒy=ð€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿ¦+ÿ€èÿÿÿïú?ÿÿþþÿþþÿÿÿþ"i}ý¤@lé Hÿÿ~ÿßþ ÿÿÿþÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿtÀ0¾¡"©&$§¢ ¤&"¦#*”/¾bŒË²MèõÿÿÿÿÏc@´_ÿÿÿÿÿÿû^[]¿ÿÿòîÿÿÿÿÿw‘ûà(8= Æ`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ?éŠýýÿÀÿÿÿÿþÿ ÿ¿¤ÿ¿¤ÿÿÿˆŸÚXoÿÿºgÿÿÿÿߣÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿûôÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÀ/ÈL®M-ŪŒ¬ì­„ ³r“{¢„B"ôÐ1ÿÿÿÿþׂ×M‹ÿüúÿÿÿÿÿØÁ¤~ø  q‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀOúa?ø~ÿÿþÿ ÿÿàéÿïéÿÿÿâ'ö‘ßßÚ0Ιïÿ÷èÿýÿÿÿÿÿÿÿàÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿ@ÿÿ÷L L+“cKqj£+kƒ+cC{1ûæ(Àl±®¤ãvaŒTût ÁEÿÿÿÿÿ€d5ôµÄÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿÿûÿ€èÿÿÿïúÿÿþþÿþþÿÿÿþ"i}ý¡Àré@Aÿÿ~ÿßÿÿÿÿÿÿþÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿtÀ.Í"¹¹²·¡92²2·2¼¾bŒ¾’:”v| ½OkC”?ÿÿÿÿøC_ëYÅÿömÿÿÿÿÿÿ_ÿŸÿø/ø…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿÔ§ÿÑÿÿÿÿÿÿÿÿÿü!ý ÿýý ÿÿÿüDþÔûûPÙÓ&À…ÿþýÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿߣÿÿÿÿÿÿÿÿÿÿÿÿÿà0ÿÿþé€F)«Kahler Asten |Å vȤ~r,`Ì1)‘ÿøü&€Ÿ †›–™ ÿýú?ÿÿÿÿÿÿÿøÿÿ¿GÿÿÿÿÿÿÿÿÿÿÿÿÿÀ`ÿÿýÓ˜SæŽÞÊäØÒèô@@@@@@@@@@@@¾ùŠ0ì®éKĈc°1ù7•¯Éÿÿÿÿà n-Wö?ÿÉaÿÿÿÿÿþAà Gï€@˜á(0€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüzÿ¦ÿ€èÿÿÿïúÿÿþþÿþþÿÿÿþ"g€}ýž|é Dÿÿ~ÿßÿÿÿÿÿÿþÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿð ÿÿÿtÀ.ü °±´2·§¹9±0±´¾bŒ¶ºB7³¦ ZηD?ÿÿÿÿøC]k[ÖÿòYÿÿÿÿÿ_ÿÿÿø)ø8  ¡¿áÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿRŸü?Gÿÿÿÿÿÿÿÿÿð ‡ô€ÿ÷ô€ÿÿÿñûKoïí6gL–ÿûôþÿÿÿÿÿÿÿðÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿ€ Àÿÿû¦x¨-½•±¸µ ½¹¸€€€€€€€€€}ó`5¼NÙFP™ÀNz`‘ÿÿÿÿÿÀ2ZÝ+ÿÿ®ãÿÿÿÿÿû¸Xß1‚ÀN0 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø ÿP'ÿÑÿÿÿßôÿÿü!ý ÿýý ÿÿÿüDþÒÀ+ûûKõÓ%€›ÿþýÿ¿ÿÿÿÿÿÿüÿÿߣÿÿÿÿÿÿÿÿÿÿÿÿÿàÿÿþé€téP #´²¹¹²·«²º:2·12¹3¾bŒ´TZ?² ‹ ÍNÁC?ÿÿÿÿøC[‹Sµ?ÿû ÿÿÿÿþgÿÿø%ø±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿù‘ÿ`÷ÿÑÿÿÿßôÿÿü!ý ÿýý ÿÿÿüDþÑ€ûûH€©Ó&ÀUÿþýÿ¿ÿÿÿÿÿÿüÿÿߣÿÿÿÿÿÿÿÿÿÿÿÿÿà0ÿÿþé€:* Wasserkuppe _|Å fd‡Q g43Æ£ÿøÿü&€žÐ †—Ö—ÜŸÿã ÿÿÿÿÿÿ ð £÷À``\ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòkþ ïþ£ÿÿÿ¿èßÿÿøCú@ÿûú@ÿÿÿø‰ý©A÷öÿÿÿÿÿÿÿÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿GÿÿÿÿÿÿÿÿÿÿÿÿÿÀP"Pÿÿÿÿÿþ**Erfurt-Weimar _|Å qöäˆD7ð4šº„ ÿÿÿÿÿ𠆵6¬+_ÿéÄÿÿÿÿÿÿ î ÷À\€¼ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÛþ Oþ£ÿÿÿ¿èÿÿøCú@ÿûú@ÿÿÿø‰ý¦À÷ö› ¦R›ÿýú?ÿÿÿÿÿÿÿøÿÿ¿GÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÿýÓ0ñ ®øPtÈ+ºdÀFèì®L%©Œ®­­Í.D­ï~’•+ñƒy³UP_—ÿÿÿÿþÖ~Õ‰sÿý&Ÿÿÿÿÿÿ×ÿÁ×ÿþ ~‚Â0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏû?ø~ÿÿþÿ ÿÿàéÿïéÿÿÿâ'ö‘¯ßÚD .™ïÿ÷èÿýÿÿÿÿÿÿÿàÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿ@€ÿÿ÷L R3KC£+c+“9ûæ(Àk#i$ÍŽãð!ø”O¿ÿ¿'ÿá4è€d4}´xcÿÿWÿÿÿÿÿüEÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿübÿ§#ÿ€èÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿþ"hp=}ý¡Á>éàÆÿÿ~ÿßÿÿÿÿÿÿþÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿtÀ’7777dballe-7.7/extra/bufr/crex-has-few-digits.bufr0000644000175000017500000000033412652630043016247 00000000000000BUFRÜb€  4}ŠtHá:eCÔ16206 Ütºt€Ç  –A1 A1!n g/±N€T=BG Ð^s‰Î`KE¹tŸòî‚€˜U™r"¸F0„ C!?ÿÿü_ÿð hÑ£F4hÏ<›>4e€#R«5XÕjU«V4hÑ£F4hÑ£F4`7777dballe-7.7/extra/bufr/generic-bug20140312.bufr0000644000175000017500000000021412652630043015476 00000000000000BUFRŒÈÿÿÞ4€ÂÀÀÁÀÁ e!À!Á !À!Á!Â6generic @_xF3˜¬¥>€€8AáU™æUO2Œ7777dballe-7.7/extra/bufr/gts-synop-linate.bufr0000644000175000017500000000035012652630043015710 00000000000000BUFRèÿß €ÇV½ (&¤¦ §'—¦$§ ª"/¾­˜uo‚A¡²Ø ÓN_=LÿÿÿÿøC‰Ë/ð ƒèd[ÿþ0qñ(P"0¾ü?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñþ¿÷èÿïÿÿÀ2Пÿÿü!ý ÿýý ¼ì£þÍÀ ûûÿÿÿÿÿÿÿþýÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿߣÿÿÿÿÿÿÿÿÿÿÿÿÿà7777dballe-7.7/extra/bufr/C23000.bufr0000644000175000017500000000423612652630043013251 00000000000000BUFRžb€e 4e}§VàDÉ`kˆ03882 žX&F:€ÉD = >–A A!—A A—ÿ¹(£í:·­þ ‰’ÀÄþÿÿÿý¾sˆÀ;0²3ÀNH§f–CÿÿùÄy,êÉ?ÿÿ80@ežY/ÿÿæÀ '³k!dôÐK6mdÿÿ™pÿÿÿÿýÂR÷lYeŽÿÿþ\`_ÿÿÿÿ÷¨(Kxe–3ÿÿù`ÍlªÄÿÿÿ(`¥“WÛÀ$|±êöÿÿüˆ‰–9\ÿÿ‰¢Æ«¡êýEXÅxÿÿþ?_ÿÿÿÿ÷¨4¨Ñ¥Æ4øÑ£F\hÑ£K4¸Ñ£F—4iq£F.4hѧÆ4hÒãF\hÑ£R*4hÑ¥Æ4¸Ñ£K4iñ£F4¸Ñ£F—4iq£FJ4¨Ñ£F—4iq£F.4hÑ¥Æ|hÑ£F.4hÑ¥Æ\hÑ£K4¸Ñ£K4iq£FJ4¨Ñ£F—4hÒãF\hÑ¥Æ4¸Ñ£F—4hÒãF\hÑ¥Æ4¸Ñ£K4iq£F—4hÒãF\hÑ©F•4hÒãF\hÑ£K4¸Ñ£F—4hÒãF.4hÑ¥Æ4¸Ñ£R*4hÑ¥Æ\hÑ£K4iq£F—4hÒãF\hÑ£K4iq£F.4hÒãF”iQ£F.4hÒãF\hÑ¥Æ|hÑ£FJ4¨Ñ£F—4iq£F.4hÑ¥Æ\hÑ£O4hÑ¥Æ\hÑ©F•4hÒãF\hÑ¥Æ\hѥƔiQ£F.4hÑ¥Æ\hÑ¥Æ4¸Ñ£O4hÑ¥Æ\hÑ£K4¸Ñ£K4jQ¥F5(Ñ£F”hÑ£FJ4hÑ£F¥4hÑ£F4`2/ÿÿß¿~ýûÿïÿ¿~ýû÷ïÿ¿~ÿû÷ÿß¿þýÿ÷ÿÿ¿~ýûÿïß¿ýÿ÷ÿß¿þýûÿïßÿ~ÿûÿïßÿ~ýû÷ÿß¿þÿÿ÷ïÿ¿ýûÿÿß¿ÿÿÿ÷ïÿÿýÿ÷ÿÿ¿~ýû÷üˆ((„Óñ€zÀDÀ%€¸ j“ ÀŒàH(xÌ œ‘‹Ý€ÀMˆ*ô êŒHA®â`v¨<@†çµr0Âha°2Š Þ‡C­¡æQ€…CÊ"rX»DoâR4¤,S*¨ø E­"öq€ÚÔn^9WÙfH ¢N‘I¾4ir7777dballe-7.7/extra/bufr/ecmwf-amdar1.bufr0000644000175000017500000000024212652630043014737 00000000000000BUFR¢b€  4}È 8Fvlœ°EU0068 ¢"ÊF€Ë–A A!8EU0068 ﹤ÉË3°±€ í:Ÿÿÿÿÿà hÑ£F͘ÓãF4hÀ7777dballe-7.7/extra/bufr/temp-2-255.bufr0000644000175000017500000003255012652630043014117 00000000000000BUFR5hNÿÿ Ù  ,-9€Á Á ÁÁ P‚‚       5 }œ VZáÕ(, ø Jº€‡T °xÓy#z°*ï5ˆ¸uJ c7$ ë&¯îƒl€S‡T °Pf¡À²+ø7è¸uJ †5Âk°pƒ€€£‡T ° PS!±+8H ¸uJ ¥4’ë°q‚€ó‡T ° P?":°«8(¸uJ Ê328k°2‚C‡T ° °($A’¯êÿ 7ȸuJ ï1ÊPjú¯²x“‡T °`%AÒ¯*ó 7(¸uJ 0\*î®òpã‡T  ô¦Aò®ªë 6¨ ¸uJ E.Šl *ꮲj‚3‡T   ’Û§‚®*ã 6(%¸uJ p,êˆ"êꮲl‚ƒ‡T  pÀ©‚>®ªë 7H*¸uJ š+Z¬$êò¯2€‚Ó‡T  À«+ÂV¯j÷ 8ˆ/¸uJ Á)êÐ%ë°ò°ƒ#‡d  PR’®b±« ¸vJ @%K #«&²r脇d  %E³.³+3 @hC¸vJ m#£8!ë:³²„c‡d °(R.´ ³ë? BH¸vJ œ!óDk>³ò&„³‡d °+4AÞ´kG CM¸vJ Æ {@kF´r6…‡d °- ü3Á®´«K CèR¸vJ ôÛ4«J´²F…S‡d °0Ðß2Ž´«K DhW¸vJ $+kF´rF…£‡d °3ưÁŠ´kG D¨\¸vJ Q“+F´rF…ó‡d °6P®¯Á¢´+C DHa¸wJ z *økB´2D†C‡t °9P“¯Æ³«; Cèf¸wJ ­bô+6³r8†“‡t °<{/Ú³+3 Ck¸wJ Ùâì«&±p„†ã‡t °>àb.AÚ²+@p¸wJ JÜ«°°ƒô‡3‡t °ApL-Ú±k?u¸wJ (*Ô«°q‡t °C€9­Ú°«>èz¸wJ Iä«°1ƒì‡Ó‡t °EÀ&/AÚ°*ÿ>ˆ¸wJ oÃk¯±ƒäˆ#‡t °Hp1Aú¯ê÷=È„¸wJ Ÿ# êö¯1ƒÜˆs‡t °K`Põ²®êï =h‰¸wJ É»"*æ®rΈÇt °Mðß±‚®*ß <(ޏwJ ó S ªÚ­²¾‰‡„ °PpÊ0ú­ªÛ ;È“¸xJ  ã*Ò­2¶‰c‡„ °S´0ê¬êË:¨˜¸xJ D ¢üjƬr¦‰³‡„ °U°¯â¬*à :(¸xJ t øªº«²˜Š‡„ °X°„/AÒ«j· 9h¢¸xJ Ÿ¢ôª¶«r”ŠS‡„ °[@n¯AÆ«*³ 9(§¸xJ Ì"ðj²«2’Š£‡„ °^@U¯Âªê¯ 9¬¸xJ ÿzì*ªª²ŽŠó‡„ °aP<.ªj§ 8¨±¸xJ 0âäꢪ2„‹C‡„ °dp"-Á¾©êŸ 7趸xJ XšØêš©²z‹“‡„ °fÀ-ÁΩ*“ 7»¸xJ ƒ:àjލòn‹ã‡„ °ipù. ¨ê 6ÈÀ¸yJ ªþòô#*Ѝ²hŒ3‡” °kÀæ0V¨j‡ 6(ŸyJ ÎýÓ'j‚§ñƒZŒƒ‡” °mðÔ0‚Чê{ 5ˆÊ¸yJ ðü»)jz§²TŒÓ‡” Àp Ã0Bš§jw 5ϸyJ û£)ên¦òJ#‡” ÀrP±0Bž¦ªk 4HÔ¸yJ 6ú‹)ªj¦²Bs‡” ÀtpŸ°Â’¦*c 3ÈÙ¸yJ Zùc'ê^¥ò6Ç” ÀvÀ2j¥ª[ 3(Þ¸yJ ~øC(%jV¥r.އ” Ày{³B¥jW 2Èã¸yJ ¢÷#4#jR¥2,Žc‡¤ À{@Oi³‚.¤êO 2hè¸zJ Çö4"ªJ¤²$޳‡¤ À} V²Â&¤jG 2í¸zJ ìôÛ$"jF¤r‡¤ ÀàD±B.¤*C 1ˆò¸zJ óÃ#ê:£²S‡¤ À‚ 3/ÂV£j7 0è÷¸zJ 4ò¢ø&ê6£r £‡¤ À„`!¯Â‚£*3 0ˆü¸zJ Yñ‹(ê.¢±ƒó‡¤ À†Ð1’¢ª+ 0 ¸zJ ‚ðC)j&¢rþC‡¤ À‰€ù1Â’¢*# /©¸zJ ²îÓ)*¡²ò“‡¤ ÀŒá±Ž¡* .© ¸{J Üí“(ª òâㇴ ÀŽðϰBŠ ª -é¸{J ìK(ª rÜ‘3‡´ À‘й°ÂŽ * -‰¸{J 7êÓ))úŸrΑƒ‡´ Ð”à¢1‚šŸió ,©¸{J eés)éòŸ2ȑӇ´ Ð— 2šž©ë ,)¸{J ŒèS$))æžr¾’#‡´ Ð™à|²‚Šž)ã +É$¸{J ¯çC(()Þ±‚°’s‡´ ÐœNl2‚~©×*É)¸{J Ôæ3 'éÒ2¬’Ç´ ÐžÀW±‚‚)Ë*).¸{J ä«()Êœ1‚œ“‡Ä Ð¡ð@0‚†›é»))3¸|J 3ãc(iº›q‚Ž“c‡Ä Ð¤°+0Š›i«()8¸|J _â#(鲚±‚‚“³‡Ä Ð§@°B’š©§'é=¸|J ŒàÛ)©¦š1‚|”‡Ä Ðª°Bš™é›'iB¸|J ·ß›)©š™q‚r”S‡Ä Ð¬à ï/š™i“' G¸|J âÞbü)©’˜ñ‚l”£‡Ä Ð¯  Û/ž˜©‡&IL¸|J Ý*)†˜1‚b”ó‡Ä Ð²p ưB¦˜)%éQ¸}J ;ÛÛ*©~—±‚\•C‡Ô Ð´ð ´°B¦—is%IV¸}J fÚ£)ér–ñ‚P•“‡Ô Ð·°  °B–—)o %)[¸}J Ù{(én–±‚N•ã‡Ô Ðº Œ0†–i[$ `¸}J ÄØ'©^•±‚B–3‡Ô à½ v¯Âr•©W$ e¸}J ñÖÂü&©R”ò:–ƒ‡Ô àÀp b/‚f”éG#)j¸}J ÕŠô&iF”1‚0–Ó‡Ô àÃ@ N¯Bj”i?"Éo¸}J KÔBð&é>“±‚(—#‡Ô àÆ@ 9¯n“©3" t¸}J {Òúì&i2’±‚—s‡ä àÉ %®‚V’©#!Iy¸~J §ÑÂà$i*’1—Çä àËÐ ­B6’) é~¸~J ÓÐ’Ì"éñ˜‡ä àÎpM¬‚6‘i  Iƒ¸~J ÏZÌ$) ñø˜c‡ä àÑ@ í-BV(û)ˆ¸~J *Î:Ü&¨öŽ0ܘ³‡ä àÔ0 Ù.Bzލnpɸ~J XÍì(hÞƒäV™‡ä àÖà Æ¯‚(&0‰’¸~J €Ëêô'¨Æ‚dH™S‡ä àÙ@̶¯‚f‹è (‰—¸~J £Êúø%(¶#<™£‡ä àÛ@ ¨¯‚F‹'ú(霸J ÍÉâô#订.™ó‡ô àÝÐ —/FŠgþ0 ¡¸J ôÈÚð%(žc.šC‡ô àà „¯b‰¨HI¦¸J Dzì'(–¤0š“‡ô àã p®ÂvˆçöH髸JMÆ‚è'hŠ~c&šã‡ô àåÀ b.‚rˆ§ê@‰°¸JoÅ¢ä'(Š€&:›3‡ô àèP P®r‰¨2ˆɵ¸J™ÄŠà'¨šƒi^›ƒ‡ô àë >®~‰h2麸JÍÃ2ä'节(R›Ó‡ô àíÐ ,®B‚ˆh€鿸€JïÂRè(¨‚hLœ#ˆ àð ®B–‡¨ˆéĸ€JÁbà*¨v€èHœsˆ àò  -¾†§ÎH ɸ€J>ÀRÜ-(^{cœÃˆ àõ` û-Ââ…gÊPéθ€Jj¿2Ü.hR|æ"ˆ à÷À ì-Âæ„§]èIÓ¸€J”¾"à.h>uŸäcˆ àú@ Ü.Bæƒç† ©Ø¸€Jµ½Rä.¨6wa€ò³ˆ àüÀ Ë®BæƒgŽ0 ݸ€JÞ¼Jä-¨:|§$žˆ àÿ ½.ʃgÊ€iâ¸J»jÜ+¨2|' žSˆ á€ ­-®‚§¾xéç¸J+ºZÜ+(&{gž£ˆ á œ­ÂÆçžhéì¸JV¹Jä-¨yf žóˆ á ®Bê€g6 ‰ñ¸J{¸bè/'þr ÔŸCˆ á ~.‚îg& )ö¸J¥·Zè.§òr`€ÒŸ“ˆ á p o.BògV8©û¸Jʶrä0göv¥öŸãˆ$ á ^.C&'r`ª¸‚Jõµjà4gîv%ô 3ˆ$ áÐ M-Ãb~§^X*¸‚J"´ZØ7gâueî ƒˆ$ á ?-ƒ‚}ç^`* ¸‚JE³‚Ø8gÖtd€æ Óˆ$ á€ 0­Ã†|çFPЏ‚Jn²‚Ü7çÆräÞ¡#ˆ$ á0 -ƒv{ç.H 긂J•±’Ô6§ºr¥Ü¡sˆ4 áÐ -^{'H j¸ƒJ¾°’Ð5g®ræÞ¡Ãˆ4 áP ¬ÃJzg&` 긃J믊Ì3çžpd΢ˆ4 áð ð¬Ã.z'X Š#¸ƒJ®šÌ1çžr&€Ü¢cˆ4 á"€ á¬Ãy§` ª(¸ƒJ?­ŠÌ1'’q&Ö¢³ˆ4 á%0 ѬÃx§P ê-¸ƒJh¬šÌ1§†od€Ê£ˆ4 á'ÀŠÂ,Ãx&öP Ê2¸„J«ªÐ2'zoe€Ì£SˆD á* ´-wfòX ª7¸„J¶ªÊÔ1gnnæÈ££ˆD á, ¥­ƒvfê` Š<¸„JÚ©úØ0gbo'Ê£óˆD á.  ™-‚úuæîp ªA¸„Jþ©"Ô.çZnç€Ê¤CˆD á1 Š­æu&æx ŠF¸„J'¨2Ì-çJn(Ƥ“ˆD á3€ |¬‚Öt&Úx *K¸„JO§JÈ-g>mh¤ãˆD á6@ l¬ÂÞsfÒ€ P¸…Jw¦ZÐ.§2miÂ¥3ˆT á8 _-Bþr¦Æ€ ÊU¸…Jœ¥ŠØ1'*k瀸¥ƒˆT á; P®"r&¶x jZ¸…Jʤ‚è2çkh¸¥ÓˆT á> ?¯2qf¶ˆ Š_¸…Jõ£Šø3'k(€¶¦#ˆT á@À 002p¦ªˆ *d¸…J#¢ƒ3'j©´¦sˆT ñCPJ!°Ã6oæ–x Êi¸…JL¡› 3æöh§¨¦Ãˆd ñF 0ÃFnæ†x jn¸†Jx £ 4æêh(¦§ˆd ñI °ÃVn&~€ Js¸†J§Ÿ› 5fÖg( §cˆd ñKà ñ°ÃVlæj€ êx¸†JÓž£5&Æe§˜§³ˆd ñN€ â°ƒJkæ6Pê}¸†Jþ³4&¶c%Œ¨ˆd ñQ Ô0C>jæ*Pª‚¸†J%œÛ3æ¦a¤†¨Sˆd ñS°‰Æ0ƒ>j&@J‡¸‡JQ›ë 4&žbfЍ£ˆt ñV ¶1Fif*pÊŒ¸‡JšÛ4¦ŽbgЍóˆt ñYp ¦±CNhf"€ª‘¸‡J¬™ó5&~`怄©Cˆt ñ\ ˜1RgeòPÊ–¸‡JÕ™ 5fr_%€|©“ˆt ñ^À ‰0CZf¥ò`Ê›¸‡J˜"ü5¦b_&€~©ãˆt ña  z/ƒ^eåòpê ¸‡J/—*ø6&V_h€ª3ˆ„ ñdp j¯ƒfdåòˆꥸˆJ^–2ü6¦F^è€~ªƒˆ„¡fð ]0rd%êˆꪸˆJ…•c7f:^)|ªÓˆ„¡i€ O°ƒzceÞª¯¸ˆJª”› 7¦.]©z«#ˆ„¡l B0ÃrbeÖŠ´¸ˆJד«6f]*x«sˆ„¡nÀ 3°ƒZaeΠй¸ˆJ’»4¦\ëx«Ãˆ”¡r "°>`eθо¸‰J;‘šü3eú\¬x¬ˆ”¡u` /C._%¾ÀJø‰Jo’ð2eê\-€v¬cˆ”¡xp .Ã^%¶ØJȸ‰J¡Šì1¥ÚZí€r¬³ˆ”¡{°ð.ƒ\å®è*͸‰JÓŽ‚è1eÆZ¯r­ˆ”¡~Àஃ[å¦ð Ò¸‰JŠè1e¶Yïn­Sˆ”¡‚ Ï.ƒZå–ðÊ׸‰J<Œjè1%¦X¯j­£ˆ¤¡„ðÀ®ƒY¥‹ªÜ¸ŠJa‹²è1%’X0h­óˆ¤¡‡P´®ƒX僊ḊJŠÒè2¥‚Wp€f®Cˆ¤¡Š§.CBWåjøJ渊J·Šä6%vV°€d®“ˆ¤¡ŒÐˆ™.C‚W%g*븊Jä‰à:e~Vo€d®ãˆ¤¡ÀŠ.CÆXeZÐ ð¸ŠJˆ*ä>%ŠQ¦R¯3ˆ´¡’°ˆ{®ƒþXä©Èêõ¸‹JE‡:ìA%ŠB”€.¯ƒˆ´¡•àl.Ä&XcÙJú¸‹Jt†RðCe~: ¯Óˆ´¡˜^¯BWã¨ð ÿ¸‹J…’ðD¥z9Ï °#ˆ´¡šàS¯RWã¨ð ¸‹J¿„êðE%z:€ °sˆÄ¡œðI¯RWãñ(‹ ¸ŒJß„JðE%~D×2°ÃˆÄ¡Ÿ?¯NWä]ˆk¸ŒJƒªðD¥vF™€6±ˆÄ¡¡05/JW$m ‹¸ŒJ%‚úôD¥nFš8±cˆÄ¡£p*¯DJVd] k¸ŒJH‚RôD¥bF€6±³ˆÄ¡¥  /DJU¤Y¨k¸JlªôDeRD™€4²ˆÔ¡§ð¯DFTäM¨K"¸J‘€úôDeJF6²SˆÔ¡ª  ¯DFT¤øë'¸J³€ZôDeBI €@²£ˆÔ¡¬@ˆ¯DFT$ž ,¸JÕºôD%6I¢@²óˆÔ¡®pö¯DBS$š  1¸ŽJ÷ôD%.Ha>³Cˆä¡° ì/DBR¤zË6¸ŽJ~rôD%"G €<³“ˆä¡²àá¯DBQ¤zË;¸ŽJA}ÂôD%Gâ<³ãˆä¡µ ×/DBQ$†0ë@¸ŽJd}"ôDe Hd>´3ˆä¡·p̯DFP¤†@ëE¸J‰|zôD¥Gc<´ƒˆô¡¹ ¯DJOär0ËJ¸J¬{ÚôDäòF£:´Óˆô¡»Ð¸¯„NNäj8«O¸JÎ{:øE$êEã8µ#ˆô¡¾®/„VN$V(‹T¸JõzŠøEäâCá4µsˆô¡!À€£/ÄbM¤2KY¸JyÚüF¤ÒBá2µÃ‰¡!Âà˜°rLä&+^¸J@y3GdÆAà€0¶‰¡!Å@‡°DvLd ø c¸Jgx‹G$º=›€*¶c‰¡!ǃ0DjK#•x+h¸JŒwãFd®6Õ€¶³‰¡!Éày0„ZJc-(«m¸‘J°wCEdž,η‰¡!Ì0n°ÄNI¢l° r¸‘JÖv› Dd–"I ·S‰¡!·d0ÄBHâ ˆËw¸‘JýuëCäŠ!‰ ·£‰¡!ÑY0„>HbL¨ë|¸‘J#uCC¤‚$Ê€·ó‰¡!Ó`O0„:G¢H¨ë¸‘JHt£C¤r$‹¸C‰$¡!ÕÀD°„:F¢D°ë†¸’JqsóC¤b#˸“‰$¡1Ø@9°„>E¢<°ë‹¸’J™sCDdV$‹€¸ã‰$¡1Úà.0ÄJDâTÈ븒JÁr“ DäF% €¹3‰$¡1ÝP$0ÄRD"PÈ땸’Jéqë Ed>$͹ƒ‰4¡1ßÐ0ÄZC¢\Ø š¸“JqC E¤6%Í€¹Ó‰4¡1â 0ÄZBâdà Ÿ¸“J4p£ Eä"% €º#‰4¡1ä€0Ä^B"Tà뤸“J[pF$$Žºs‰4¡1æðú±bA"Tè멸“Jƒo[F$ $Ž€ºÃ‰4¡1é`ð±^@"@è뮸”Jªn³Eãú#N»‰D¡1ëàæ1^?b0à본”JÔnEãò#»c‰D¡Aî Ú±f>b@øë¸¸”JmKFãÞ$Ѐ»³‰D¡AñÎ1~=¢I뽸”J0lƒH£Ò$€¼‰D¡AôPÃ1D’<¢=븕JWkãIcÂ#€¼S‰T¡Aö¹±D–;â9ëǸ•J{kSIc¶#‘¼£‰T¡Aøà°1D–:â5ë̸•J j»Icª#€¼ó‰T¡Aû0¦±Dš:b5ëѸ•JÇjIã¢"Q½C‰T¡AýÀœ1„¦9bëÖ¸–Jïi{JcŽ$T½“‰d¡R ’±„ª8¢E@ Û¸–J hÓJã‚"R€½ã‰d¡R ˆ±D²7¢(ëถJ <h;K#v Q€ ¾3‰d¡R1D¶6áýË帖J dg£K£f  ¾ƒ‰t¡R€t±DÂ6"(Ë긗J ‹gLãV’€ ¾Ó‰t¡R j±DÚ5!ù(Ë︗J ¶f[NcJÓ€ ¿#‰t¡R °`1„î4aý8Ëô¸—J äe£Oc>“€ ¿s‰t¡R°T²þ3añ@Ëù¸—J!dó$P#. ¿Ã‰„¡b`J2E 2¡ñHËþ¸˜J!<dK$Q#T€ À‰„¡bð@2E1¡åH̸˜J!ec«$Q#U Àc‰„¡bp62E0¡åX̸˜J!‡c#$P£€ À³‰„¡b.2E /ááXÌ ¸™J!¬b›$P¢úÖ Á‰”¡bÐ%2… /!Ù`̸™J!Ðb(PâîV ÁS‰”¡b²….aÑ`̸™J!òa‹(Q"âÖ€ Á£‰”¡r 0²…-¡Å`̸™J"a ,QbÖ€ Á󉔡r"p† 2Å,áÁhÌ!¸šJ"8`ƒ,Q¢ÎW ÂC‰¤¡r$ ²Å,¡ÁpÌ&¸šJ"\_û,R"ÂW€ “‰¤¡r&Ðû²Å"+¡½xÌ+¸šJ"~_{,R"¶W€ Â㉤¡r(ðó²Å"+!±x¬0¸šJ"¢^ó,R"®— Ã3‰´¡‚+0ë2Å"*¡¥x¬5¸›J"Æ^k0Rb¢W€ É´¡‚-€â³&)¡€¬:¸›J"ê]ã0R¢– ÃÓ‰´¡‚/ÐÙ³*)!¥ˆ¬?¸›J#]S4R¢Š Ä#‰´¡‚2PгE&(a¬D¸›J#7\Ë4R"~Ù€ Äs‰Ä¡’4È3…'¡™˜¬I¸œJ#\\C8QbvY€ ÄÉġ’6𿳅'a•˜¬N¸œJ#[»LË£Š¡ÂoÐü³ƒ# `¸L¼¸¡J'O‹80"F‹€ËóŠ¡Òr@õ3Bî$ d°LÁ¸¡J'8O0."JJ€ÌCŠ¡ÒtÐí2‚Ú$`0˜LƸ¡J'bN‹$-bBH€Ì“Š¡Òwpä±ÂÒ#ßôxL˸¡J'ŽN ,â=ýÌ㊡Òz@„Ü1Ò#ŸÀh,и¡J'»M{ -b5ü€Í3Š¡Ò|ðÓ°‚Þ#Äp,Õ¸¡J'âM.¢1ûÆ€̓Š¡ÒPÌ0Bö"ß°h,Ú¸¢J( L‹0"-ú†€ÍÓŠ$¡ÒÐ݃"Ÿœ`,߸¢J(3L 1"%úÎ#Š$¡Ò„¼±C"œh,丢J(^Kƒ1¢)ú€ÎsŠ$¡Ò‡`´2C#¸h,鸢J(ŒJû,1"-ú†€ÎÊ$¡ÒŠ0«3C"ß°h,J(ºJs¸¤J+|B³0$"…òCÔŠD¡ò¹0'²‚F'ß0-C¸¤J+ªB;($¢yñÃÔcŠD¡ò»Ð ²ÂN'ß0-H¸¤J+ÔAÓ4%¢…ðÃÔ³ŠT¡ò¿ 3‚b'ß0-M¸¥J, AC<&¢yðÃÕŠT¡òÁð´n'Ÿ 0-R¸¥J,4@Û<'"}òÃÕSŠT¡òÄ  ³Ân'ß(0-W¸¥J,`@c4&¢óƒ€Õ£ŠT¢ÇP3Bj(D8-\¸¥J ,Š?û0&âyóÀÕóŠT¢ÊCü3v'_ 0-a¸¥J ,¶?‹8'¢õƒ€ÖCŠT¢̰õ³Â~'ßT8-f¸¥J ,ä?H("uòÃÖ“ŠT¢Ð ìµB‚'Ÿ0-k¸¥J ->‹d'¢qñCÖãŠT¢Ó°ä7Br&ß0-p¸¥J -W=û€&bqï‚€×3ŠT¢×Û¸ÂZ'ß0-u¸¦J -Œ={”$b‘òC׃Šd¢Ú€Ó9B6)_0-z¸¦J -Â<ó”""‘ð‚€×ÓŠd¢ÝÐË8Â(ß0-¸¦J!-û·ú(^ü(-Þ¸§J"1ç3»tbï€ÞŠt¢# 87€Ò'Þô(-㸧J"23Sx ¢yð€ÞcŠt¢##`1·@Â'ø(-踧J"2O2ãp bqï‚€Þ³Št¢#& +6ÀÊ'^ð(-í¸§J"22ƒl âqïB€ßŠt¢3)Ð$·€Ò'Þð(-ò¸§J#2¹2ˆ ¢ðÃßSŠt¢3-@ºâ(<8-÷¸§J#2í1«¸byóƒ€ߣŠt¢30€¼'_ 0-ü¸§J#31KÔ"mñßóŠt¢33Ð>2&ß0.¸§J#3T0ãè¢qïB€àCŠt¢36ÐC ?2'ä(.¸§J#3‡0ƒô"qï€à“Št¢3: ¿ '^ô(. ¸§J#3½0ôbuí‚€àãŠt¢3=`þ¾Àê&Þ¸ .¸§J#3ï/»Ü"iì€á3Št¢3@°ø<Àæ&À(.¸§J#4&/SÀâYìB€჊t¢3D Bñ»€ö%^À(.¸§J#4\.ë¼â]ë‚€áÓŠt¢3GPë¼Àþ%Þ¨ .¸§J#4.“äâ]êÂâ#Št¢3J å¿Á%Þœ .$¸§J#4É.$¢Uë€âsŠt¢CNpÞÂÁ%´(.)¸§J$5-¼8¢Mê€âÊt¢CQÐØÄ%¸(..¸§J$55-\@bMê€ãŠt¢CTðÓCÁ$^°(.3¸§J$5l,ü8bEé‚ãcŠt¢CX`ÌÂÁ#žœ(.8¸§J$5¢,œ$â5èB㳊t¢C[ ÇBþ"ÞŒ .=¸§J$5Ñ,Dâ)ê€äŠt¢C^ ÁÂ"ž˜(.B¸§J$6+ì$¢%éB€äSŠt¢CaмBÁ"œ(.G¸§J$66+”4"!èB€䣊t¢Ce¶CÁ*"¤(.L¸§J$6j+<<â%êB€äóŠt¢ChP°ÃÁ*!Þœ(.Q¸§J$6›*ä<"ê€åCŠt¢CkP«ÃA!Þ¤(.V¸§J%6Ó*Œ(âêB€哊t¢So¥B Þ(.[¸§J%7 *,b ê€åãŠt¢Sr0B A !^È0.`¸§J%7:)Ü¢ìæ3Št¢Su@šÂ!Þ¨(.e¸§J%7l)„$âê‚€惊t¢Sx€•B !ž”(.j¸§J%7§)$,bèB€æÓŠt¢S|ÂÀþ!Þ˜(.o¸§J%7Û(Ì0¢!ê€ç#Št¢SpŠC€ò"Þ (.t¸§J%8(|8"5ì€çsŠt¢S‚p…CÀî#¸(.y¸§J%8A(,@")êB€çÊt¢S… €D@ú"^œ(.~¸§J%8t'ÜHâ)é‚€èŠt¢SˆÐ{Eþ"ž”(.ƒ¸§J%8§'„Xb-é‚€ècŠt¢SŒuÆâ#^œ(.ˆ¸§J&8Û'4d b-èB賊t¢c qF€®"Þ„ .¸§J&9 &ìl â1é€éŠt¢c’pkÆÀž#ž (.’¸§J&9B&”l b5ë€éSŠt¢c• fÆÀ¶#¬(.—¸§J&9t&Ll "1êB€飊t¢c™BaÆ@Î# (.œ¸§J&9¨%ü\ b)é€éóŠt¢c›Ð]ÄÀÖ"ž (.¡¸§J&9Õ%´@ â)ëB€êCŠt¢cžàXÀÂ"Þ¼(.¦¸§J&:%l4 ")í꓊t¢c¢TC@¢#¸(.«¸§J&::%4 "-ë€êãŠt¢c¥0OÀŠ"œ(.°¸§J&:r$Ì<"è€ë3Št¢c¨°JD@~!^|(.µ¸§J&:¥$„D¢éB€냊t¢c¬EÀv!^”(.º¸§J&:Ý$, " è‚€ëÓŠt¢c¯@@Àv l(.¿¸§J&;#ì"æBì#Št¢c²P<@À– žd .ĸ§J&;?#¤ â ç€ìsŠt¢cµp7Â€Æ žh .ɸ§J&;l#d0 b æ‚ìÊt¢c¸ 4CÖ Þ|(.θ§J&;—#$0 âç€íŠt¢cºÐ0BÀ¾!p .Ó¸§J&;Ä"ä$ " çB€ícŠt¢s½Ð,B@ª!(.ظ§J';õ"¤$ bê‚€í³Št¢sÀà'ÂÀ¦!ž˜(.ݸ§J'< "d8 ¢è‚€îŠt¢sÃ@$Ä@ª!^x .⸧J'ä!åä‚ñ#Št¢sáðûÊFD /¸§J'>:œ¸ááå€ñsŠt¢så`÷Í€:žd(/¸§J'>p \ì¡ÝæB€ñÊt¢sè°óN€:žd(/¸§J'>§Ð¡Íä€òŠt¢sìïJ:ž0 /#¸§J'>ÝÌ`áÅâBòcŠt¢sïpêÃJ^$ 7777dballe-7.7/extra/bufr/simple-generic-group.bufr0000644000175000017500000001601012652630043016530 00000000000000BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈ[˜\™]È € 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ[ˆY]›È[ˆ™[È=ÙÙ[™\šXÈ A3<˜Si0~7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈ™\™ÚX[›È>YÙ[™\šXÈ A3!P[¸ ˆ@7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ[ ÐYØ]H›ÛÙÛ™\ÙH?YÙ[™\šXÈ A3aÏ:ŸÀ‚ 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÛÜ\›È?ÙÙ[™\šXÈ A3wk’K# }P7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÛÜœ™YÙÚ[È@YÙ[™\šXÈ A3f…R1ŠÀ‡P7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ]œšXYÛÈ@™Ù[™\šXÈ A3aFR+#Pš°7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ\œ[™]H@ÙÙ[™\šXÈ A3&¡ÒV40 P7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈ]™^ž›ÛHAÙ[™\šXÈ A3T÷’K±0~7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈY^ž›Û\˜HÙÙ[™\šXÈ A3U´RD ƒ@7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ[ Ð[Ûš[ÈÙ[™\šXÈ A3UwRHù`€7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ\Ý[Ø[ˆY]›ÈÙ[™\šXÈ A3FÒE©@ 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXțܛZYÚ[™HYÙ[™\šXÈ A3SÄÒ4߀™ 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈšX™[ÈYÙ[™\šXÈ A3€E’"Å †°7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ\Ý[›Ý›ÈHÛÝÈ™Ù[™\šXÈ A3o«’,Éà„07777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ\œ[™]HÙÙ[™\šXÈ A3LbR+2@7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈ[ÛYš[Üš[›ÈÙ[™\šXÈ A3>’-ááB€7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈY]™HHÝ\ÚYÛ˜[›È™Ù[™\šXÈ A3j&’žÓ7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈZ\˜[™ÛHYÙ[™\šXÈ A3txÒ7{à‚ 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÜÝ[]È™Ù[™\šXÈ A3cÒL×À}ð7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈ™YH˜Y[ž˜HÙÙ[™\šXÈ A38âM£Ð‡7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÝ\Ù\˜ÛÛHÙÙ[™\šXÈ A3!óÒOàä 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ[ˆšXÛÛÉÈÙ[™\šXÈ A3ƒ¢Ò¦ð’@7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ\Ý[^ž›Èš[[›ÝˆYÙ[™\šXÈ A3×Êà‰Ð7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ[ˆ™[XÙHÝ[[˜\ˆÙÙ[™\šXÈ A3n›’:( ‚7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈY[HØ[H›ÛÙÛ™HÙ[™\šXÈ A3[=Ò>-ð„Ð7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ\ÜÛÈ[Ü™[HYÙ[™\šXÈ A3FèRI‚ð7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈ[ܘÚX[›È™Ù[™\šXÈ A3S’_2P‘P7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈ[ÙYÛX[˜H$YÙ[™\šXÈ A3)­’JÑ‘*À7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÙ[\š[›È›ÙÚY\˜H|Ù[™\šXÈ A3fÓÒINð}ð7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈZ\˜X™[È|ÙÙ[™\šXÈ A3o,’B-À€ 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈ›ÛH™YÜØH ™Ù[™\šXÈ A3Nc’;øP‘P7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÛÛÜ››È(ÙÙ[™\šXÈ A3z’'4à†7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈšY[ž˜H)Ù[™\šXÈ A3u0Ò ³` 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈXZX]XÛÈ)YÙ[™\šXÈ A3b˜R#´°Ó@7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÚ\ÜØH)™Ù[™\šXÈ A3zîR%Ї7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÚ]š^ž˜[›È.YÙ[™\šXÈ A3\´R'cpÍ 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈYY\Ø[›È.™Ù[™\šXÈ A3fx"E€7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÜYÛ›È.ÙÙ[™\šXÈ A3s™$/PŠ 7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ\Ø]XÛÈ/Ù[™\šXÈ A3]<Ò$ûép7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØ[\ÙØ[X[›È/YÙ[™\šXÈ A3a¨3€Ð‰€7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈÛÜ[HHØ\œH çYÙ[™\šXÈ A3ióÒ6b€„07777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈØZ[˜YÛÈ3Ä™Ù[™\šXÈ A3thÒ'÷`…À7777BUFRœÈÿÿè$€ÀÂÀÂV@YÙ[™\šXÈœš\ÚYÚ[HD\Ù[™\šXÈ A33fRI‡€¶Ð7777dballe-7.7/extra/bufr/pilot-gts4.bufr0000644000175000017500000000042612652630043014505 00000000000000BUFRb€[  4[}Õm HϦi'ì10954 m·žF4€Á  Á Á ÁE   –A A!Ýûî«m¤Ÿ°‘ŸL… ÿþÚ0Ÿÿ‚Æóÿð@b˜ÀBhƒÿÿoÿÁÓâ`ÿø LÜ$?ÿ 茗ÿà¡Ò maÿþDÀF„ HB |hÑ£F4hÑ£F4¸Ñ£K\hÑ£K4¸Ñ£K4¸Ñ¥Æ7777dballe-7.7/extra/bufr/synop-longname.bufr0000644000175000017500000000252612652630043015450 00000000000000BUFRQÚ Û €ˆ#ÇPˆ"‚&´¹µ·¶1 »0¹/¶( •Àòd´¦® `M÷AÆ?ÿÿÿÿøC\{UMP ðdÿÿÿÿþÈt¨P(0xÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðSþ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø2ô ý¥`'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñ™ª;Ë{‘ƒ+‘ûb€Àhÿ¸¥ºh!J¥¤ò>ÿÿÿÿÿ€d5嵩ܯ>‡ÿÿÿÿÿé‡i†‚# @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿èCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚0@ŸÚ2?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥¡:²0¸2¹º(2¹º9½2·:67¹4·1–µº¶:2¹:¶2º/¶( š*_Û ‰ÎñA3ÒÿÿÿÿøCfË\Í ùÄÿÿÿÿþ4u(`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ŸôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁo Oí;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒÜ‘Xœ™XÙ[ˆÛG,‘3¢; åö' eäÿÿÿÿü!­­'xK?ÿÿÿÿÿ2:Ç”0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁOú@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿà'ö¤oÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆsJl.M¬­Œ­d튡"v–kù…B‹ÐPr÷ÿÿÿÿþׂÖWh½ôÿÿÿÿÿ™cÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿà'ý?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðBHûU@/ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿã:åV72övç’öŀσ KžãíwÉÎh7{KÿÿÿÿÿÈk…jï´_8ÿÿÿÿÿ倱åÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðþ„?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø!$ ýš@%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñž²›Ó+;+![«c£+“«c+¡ûb€Àgô…¦*,€–ä÷”<åÿÿÿÿÿ€d6µÇÙ¯%‡ÿÿÿÿÿã@Xò†ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø ÿ@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü’þÓðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø7777 dballe-7.7/extra/bufr/gts-amdar1.bufr0000644000175000017500000000025012652630043014432 00000000000000BUFR¨N€ Ù (ÿÿ¬#ö  16€„Ë@  g B K L % ' M*+,-„A…>ÑUL Í?ÿíæ?I±}ö|½_Ñày’Ÿ‡¼2~?ÿõ_ÿþÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿþ7777dballe-7.7/extra/bufr/obs1-140.454.bufr0000644000175000017500000000026212652630043014156 00000000000000BUFR²b€Œ4Œ}aE0äbOøLEIB ² ´ŽF€Ç  –A A!DLEIB _XA •‘¶€Ë€ ‚9¤@¤#­2¿'¦ Ïb4hÑ£F4hÑ£F6lhÑ£7777dballe-7.7/extra/bufr/gen-generic.bufr0000644000175000017500000025502612652630043014672 00000000000000BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀîP  ›e“ ±^2d dÈD?ÿW@þ®ƒì™ ÿÕÐ?ÿ« ,™¨(ј@€}VL€F”VjÉ5Š€€*¨ 2d € LÉœ2d° ì™ ]“ T( “ %?R€ @" “ `N H ?Kë#)èðýú‚z7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  I“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«  ™¨Ñ˜@€|¶L€F”VÞÉ5’€(x 2d € |Éœ2d° l™ u“ Te2d,€²dB0 Q@ PA²dL ©@@Pì}de 3ª ,Ð?`7777BUFRrÈÿ  ²ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ¢P  ž]“ ±ô2ddÈD?ÿW@þ®€ ÿÕÐ?ÿ« L™§ðј@€|¶L€F”VÌÉ5|€€(Œ 2d € L€Áj€ $àƒgÖFR Z¡,D}d7777BUFRrÈÿ  ²ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ¢P  e“ ²X2ddÈD?ÿW@þ®€ ÿÕÐ?ÿ« L™§ìј@€{4(@F”VÈÉ5‚€) ¡B € L€Áj€ "Ÿ@JWÖFR\dmãÈÔ7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  ›9“ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«¡ ™§í“ ј@€~vL€F”VÊÉ5”€€( 2d € 2É™2df à Q“ Te2d,€2dB@ vÀ Pd qçÖFR%uí3±ˆü7777BUFRôÈÿ  ôÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  –dÈ*fL€ÇÐÉ“ ÿý]ÿúº2d$ÿW@ÿþ®„2dŸ`F”@XÉ5v2d€( € |Éš²d° Q“ Te2d,€²dB@ Gà P€}§ÖFRB§á"»†7777BUFR$Èÿ  ÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ždÈ*'vL€ÎÉ“ ÿý]ÿúº2d$ÿW@ÿþ®ƒ2dŸ€F”@0É5{2d€( € 2Éœ2dr ì™ m“ Ti2d,€2dB@ d P(A²dL Ä©@@!ß}de 4)„TÊ0ÊÀ7777BUFR®Èÿ  ÐÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÀP  ‘)“ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ¬™§ÔÑ¥€¡2d \`  U@ 2d&l™‚Õ@ðˆ”dÈUl™ (ü/¬Œ¤‚B‚NÄúd7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ™Ý“ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§ìј@€|¶L€F”V²É5q€€*X ²d € dÉ›²dr Œ™ ]“ Te2d,€2dB0 m` P(A²dL ©@@;æ}de 3•åL€W 7777BUFR®Èÿ  ÐÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÀP  ’M“ µÜ2ddÈD?ÿW@þ®€P€ ÿÕÐ?ÿ« ,™§ôÑ¥€œ2d `   %²d&Ì™‚–€@ðˆ›dÈUL™ ( ü﬌¤pPÂ<êªT7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  šù“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™§ôј@€}L€F”VÐÉ5~€€*D 2d € 2É›2dr ™ e“ Te2d,€2dB@ Z  P A²dL ©@@Lë}de 3ÁYOÀ7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  i“ ³è2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§Üј@€|ÆL€F”VðÉ5‘€(È 2d € Éš2d T À Q“ Ti²d,€  ,÷¾²2ÔN Ëh`7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  ž“ ±ô2ddÈD?ÿW@þ®€P€ ÿÕÐ?ÿ« ,™§ðј@€}L€F”VôÉ5r€€*¼ 2d € 2É™2d T À ]“ Te2d,€  -ø>²2ÒZ êX07777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  ž)“ ³è2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§àј@€|–L€F”VÈÉ5Œ€€( 2d € Éš²d T À Q“ Tf2d,€  /ø¾²2Û¡ !Ù˜p7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žÍ“ ³„2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§Üј@€|öL€F”VÌÉ5‚€( 2d € É›²d T À Q“ Te²d,€  1€ú>²2߉ )üè 7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  Ÿ-“ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«  ™§äј@€}L€F”VêÉ5y€€(( 2d € Éš2d T À Q“ Te²d,€  4€ú¾²2Ø6 +Ѩ 7777BUFRrÈÿ  ²ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ¢P  žÉ“ ±ô2ddÈD?ÿW@þ®€ ÿÕÐ?ÿ« ,™§èј@€|VL€F”VæÉ5l€)ô ²d € L€Áj€ $ÀgÖFR<úÁ';m87777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  Ÿ“ ³è2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§ôј@€|”(@F”V´É5”€€*l ¡B € Éš2d T À Q“ Te²d,€  7û¾²2߉ =À€7777BUFRÈÿ  üÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀæP  •%“ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™¨Ñ¥€2d f€   2d' ™,@&@ˆ›dÈU dÈ„€ @} PƒdȘˆR€€äòúÈÊ@f†#Ò¼`ïÀ7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  –E“ ²X2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§øÑ˜@€|4(@F”V°É5„€€(< ¡B € dÉš²d Z À ]“ Te²d,€2dB ¯ Pp×ÖFR5·a JÈ7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  Ÿ!“ ´â2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§üј@€|¶L€F”W&É5‡€(< 2d € 2É™2d° Q“ Te2d,€2dB@ Q@ P€çÖFR4oA )ˆ$7777BUFR¾Èÿ  ØÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  dÈ*2–L€É`É“ ÿý]ÿúº2d$ÿW@ÿþ®²dŸF”@pÉ5u2d€) € € Éš²d T À Q“ Tg2d,€  >¾²2¤t …¨Yð7777BUFRôÈÿ  ôÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  dÈ)ë–L€ß@É“ ÿý]ÿúº2d$ÿW@ÿþ®¡BŸ@F”@ÔÉ5S2d€) € € 2É›2dÛ à Q“ Te²d,€2dB@   P`€gÖFR3'!"ü0 7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žù“ °!B*dÈD?ÿW@þ®ƒì™ ÿÕÐ?ÿ« ,™§ØÑ˜@€|VL€F”V¬É5£€(´ 2d € É™!B T À Q“ Te²d,€  I>²2¤ñ +i€ 7777BUFRÈÿ  „ÀÁÂÀÁ !!À!ÃÀÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀ|P  ž…“ °ÿþ®ÿý]dÈ0? ŒÀá²d4 ¶†L€¬ÐtRÀ“ TL Eõ‘”€ÌÉÈID‚ÀÕ€7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žé“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«  ™§Ðј@€|fL€F”VÊÉ5£€€* ²d € Éš2d T À Q“ Te²d,€  J >²2™¶ +i€`7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žå“ ²X2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™§ðј@€|†L€F”VÌÉ5—€(P ²d € Éš2d T À Q“ Te²d,€  J€ ¾²2o /GÀ7777BUFRrÈÿ  ²ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ¢P  žá“ ³è2ddÈD?ÿW@þ®€ ÿÕÐ?ÿ« ,™§ìј@€|L€F”VÔÉ5ˆ€€(Ü 2d € L€Áj€ $ àgÖFR/ë"€}$7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  ““ ³è2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§øÑ¥€¢2d Y   UÀ 2d&왂€@ó&@ˆ›dÈUL™ @L™†("`”FŒ™¼*@P*YH ŸïŽÉì 07777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  š‰“ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« Œ™§Ðј@€|FL€F”VÜÉ5ƒ€( 2d € É›2d° ™ ]“ Te2d,€²dB@ M€ P(A²dL H©@@¬}de 2ë(KÖ€Q7777BUFR®Èÿ  ÐÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÀP  ”¡“ ´â2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§ìÑ¥€±2d b    2d&Œ™‚Õ@ðˆ”dÈUl™ (`o¬Œ¤]âL,ê(7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žé“ µÜ2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«  ™§Üј@€|¶L€F”V¦É5…€(( ²d € Éš²d T À Q“ Te²d,€  _€¾²2|ç 8nØÀ7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žé“ µÜ2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§ôј@€|6L€F”VÐÉ5‡€(È ²d € É›²d T À Q“ Ti2d,€  g>²2Qï [XP7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  Ÿ“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§øÑ˜@€|–L€F”VàÉ5£€€(Ü ²d € –Éœ2d T Ì™ m“ Th2d,€²dB Ô€ P(B2dL ©@@Ö!}de 2]ŽKnP2`7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  ™y“ ´â2ddÈD?ÿW@þ®€P€ ÿÕÐ?ÿ« ,™§øÑ˜@€|6L€F”VÜÉ5…€€)ô ²d € 2É›²d T À ]“ Ti2d,€  l>²2BÌ (\@+À7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  š“ ²î2ddÈD?ÿW@þ®€P€ ÿÕÐ?ÿ« L™§üј@€{ÖL€F”V¬É5•€(( ²d € |Éœ2d Z À ]“ Ti2d,€  p¾²218 *e)`7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  Ÿ“ ³è2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«  ™§ØÑ˜@€|ÖL€F”VêÉ5v€(( 2d € Éš²d T À Q“ Te²d,€  s>²2BÌ B› 7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žI“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§àј@€|fL€F”VüÉ5 €€(´ ²d € Éš2d T À Q“ Tf²d,€  t¾²2-P L_7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  žÕ“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§ôј@€|ÆL€F”V¶É5‘€€( 2d € dÉœ2d° ™ U“ Te2d,€2dB@ Q@ P@B2dL ©@@ë+}de 2U¾[µ4@7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  “ ±ô2ddÈD?ÿW@þ®€P€ ÿÕÐ?ÿ« l™¨Ñ˜@€|&L€F”VÈÉ5˜€)¤ ²d € 2É›2d Z À ]“ Ti2d,€  w€>²2"’ .Þè!7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ž™“ ²Š2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™¨Ñ˜@€|VL€F”VøÉ5ƒ€( 2d € –É›2d Z Ì™ m“ Te2d,€²dB ¯ PB2dL H©@@ó.}de 2.®ey5 7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  ›½“ ²Š2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§èј@€|fL€F”VðÉ5‰€(ð ²d € Éš²d T À Q“ Tf2d,€  z¾²2? 7ž€$@7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ž“ ³„2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™¨ј@€|(@F”VøÉ5†€€)T ¡B € °Éœ2df Ì™ m“ Tf2d,€²dB ‰€ P(B2dL ©@@õ0}de 28rZP2À7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žÕ“ ³è2ddÈD?ÿW@þ®€P€ ÿÕÐ?ÿ« ,™§ØÑ˜@€|L€F”V°É5Ž€( 2d € dÉœ2d Z À e“ Ti2d,€  ~€>²2ÿj @úX7777BUFR®Èÿ  ÐÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÀP  “ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§ØÑ¥€¡2d Y  Z@ 2d&Œ™‚Õ@ðˆ”dÈUL™ ( @o¬Œ¤GÉÂUýðX7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  ž“ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§ØÑ˜@€|†L€F”VèÉ5’€(´ 2d € Éš2d T À Q“ Te²d,€  ‚€>²2] U˜7777BUFRôÈÿ  ôÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  dÈ*/L€Ñ0É“ ÿý]ÿúº2d$ÿW@ÿþ®²dŸpF”@tÉ5k2d€(ð  € 2É›²dR ` Q“ Th²d,€2dB0 1` PpƒWÖFRíA)ç š7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ©“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«  ™§äј@€{ÖL€F”VðÉ5€€), ²d € 2É›²dr L™ ]“ Te2d,€2dB0 vÀ P(A²dL ©@A!8}de 1ëL‡§=7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  ˜i“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§Ôј@€zæL€F”VøÉ5†€€), 2d € Éš²d T À Q“ Ti2d,€  œ>²2ñA cø¨.7777BUFR®Èÿ  ÐÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÀP  A“ ³„2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§ÜÑ¥€ 2d ]€  i@ 2d&Œ™‚Õ@ðˆ”dÈUL™ ('€¯¬Œ¤3äV2 7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  Ÿ “ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™§ðј@€|æL€F”V¼É5–€( 2d € Éš²d T À Q“ Tg2d,€   >²2ëe paÀð7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žÙ“ ³è2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§èј@€|FL€F”VôÉ5€€) ²d € Éš²d T À Q“ Tg2d,€  ¢€ >²2á$ c\h 7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  1“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§üј@€}L€F”VèÉ5™€€)¸ ²d € Éš2d T À Q“ Tg2d,€  ´"¾²2ÂÞ uCÀ€7777BUFRÀÈÿ  ÚÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÈP  žÁ“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§èј@€|L€F”WÉ5e€€(Œ 8²d € É™²d T À Q“ Te²d,€  µ#>²2•ò [¡@ð7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  šy“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§øÑ˜@€{¶L€F”V¸É5n€*” ²d € –Éœ2d Z À m“ Tf2d,€2dB œ@ P„wÖFR•a&Æ=7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ž=“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™¨Ñ˜@€{t(@F”WÉ5n€€* ¡B € 2É›²d° ™ ]“ Te²d,€2dB@ >€ P0A²dL ©@A•H}de 0å”j[4 7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  œ™“ ³è2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™§ðј@€zöL€F”VøÉ5x€(Œ 2d € |Éœ2d T À ]“ Th²d,€²dB Ô€ P „—ÖFR ÜA&óÐö7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  Õ“ ³è2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ˆP€§Ôј@€{FL€F”W,É5u€)à $2d € 2Éš²d T À q“ Ti2d,€2dB Ô€ P@„·ÖFRˆ!*b¸–7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ž¥“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«¡ ™§èј@€{¶L€F”VÔÉ5“€)ô C2d € 2Éš²dR ™ m“ Te2d,€2dB@ >€ P(A²dL ©@A¦L}de 0ÚÖ¨œ€3`7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀîP  ž¡“ ³ 2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§äј@€{6L€F”WÉ5x€) ²d € °Éœ2d T Ì™ m“ T(“ À%R€ À"“ `™ H  hBkë#)†a€’ݨ—7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ‘“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™§ðј@€{(@F”VÈÉ5‹€(d ¡B € –É›2d Z Ì™ m“ Te2d,€²dB ¯ P0B2dL ©@AÅP}de 0z(…ž03`7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  žÑ“ °ú2d dÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§ðј@€|†L€F”VèÉ5ˆ€€(d &²d € LÉ›²dr ™ e“ Te2d,€²dB@ vÀ P(A²dLYt©@AÌR}de 0¡8™ö€3`7777BUFRBÈÿ   ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀP  šÉ“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™§èј@€y´(@F”V¤É5¤€(´ 1!B € 2Éœ2dR ™ m“ T( “ %©2dR€ " “ `s HÔ0Ù2'Ð2dV€  ë)¾²20b 'WØ$ð7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ñ“ °È2d dÈD?ÿW@þ®‚Ì™ ÿÕÐ?ÿ« L™¨ј@€{†L€F”VÔÉ5¢€€(  !²d € 2É›²dR ™ U“ Ti2d,€2dB@ 5 P(B2dL ©@AàT}de 0S›ÿP7À7777BUFRBÈÿ   ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀP  ›ý“ °È2d dÈD?ÿW@þ®‚Ì™ ÿÕÐ?ÿ« L™§üј@€{&L€F”V„É5‹€)h ²d € dÉœ2d& L™ U“ T( “ À%õ2dR€À"“ `2HÔ12'x2dV€ !0¾²2È= à˜! 7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀîP  œu“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§øÑ˜@€z–L€F”V˜É5•€(Œ $2d € LÉœ2dR ì™ m“ T( “ %©R€ @"“ ``àH  Cë#)‰û`–ù‚7777BUFRTÈÿ  *ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀ P  u“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§ðј@€{4(@F”VÆÉ5œ€(  )!B € LÉ›²dR l™ q“ Te²d,€²dB0 -¦L€ PA²dL ©€F&@áíÆL€ Ð%P†GÖFR1ñ( Ö7777BUFRTÈÿ  *ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀ P  žI“ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™¨ј@€y¦L€F”VÈÉ5•€€)Ì ²d € LÉ›²dŠ l™ Q“ Tf2d,€²dB8 &&L€ PC2dLl©€F&@áíÆL€ Ðð:7ÖFRõa …+*7777BUFR:Èÿ  ”ÀÁÂÀÁ !!À!Ã!!À!Ã*!!À!ÃÀÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀˆP  žÉ“ °´2d^à €Gÿõtÿêè+&@€)ö4f žÉ“ ‘¥„2d _  Z,™ (€~¬Œ¤ßûz8±ð@7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  žÉ“ °–2d dÈD?þ®€ý]¹@?ÿW@þ®l™ ÿÕÐ?ÿ« ¬™§Ù“ ј@€{ÆL€F”VÉ5z€€(ð ²d € Éš2d T À Q“ Tf2d,€ €û¾²2€3¨õ³€@7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  ž}“ °á2d dÈD?þ®€ý]¬?ÿW@þ®‚Ì™ ÿÕÐ?ÿ« Ì™§á“ ј@€|6L€F”V2É5€€(ð ²d € Éš²d T À Q“ Tf2d,€²dB¡íÀ P@?—ÖFRu-Ý€CT7777BUFR¶Èÿ  ÒÀÁÂÀÁÂ!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!ÃÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀÆP  K&@@ÿõtÿêèfñÿý]ÿúºÉ` À €'5$i@bŒ™X8èžk&@¨%€(I“ $ã&@( 2HÕ“ 0;c&@h bÀ3ë#)À/8‡™Š‚7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ž•“ °ú2d dÈD?ÿW@þ®‚Ì™ ÿÕÐ?ÿ« ì™§øÑ˜@€|ÖL€F”VJÉ5‚€(  ²d € É›2df l™ ]“ Tf2d,€²dB0 vÀ P0@2dL°©@(!ý}de 7?áRw5`7777BUFRèÈÿ  îÀÁÂÀÁ !!À!Ã!!À!Ã!!À!Ã>!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÜP  ž5“ °ú2ddÈD€GÿÕÐÿ« UhÇÿêèÿÕÐ-“ #ÿúºÿõt“ Àý²d3OŽÉHÒ€ ÌY2°0ÐöL€P2VL€Áj€ xDJ2d*€ ¶L€‚0?÷ÖFRr)U!:øv7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  ž¥“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«¡ ™§øÑ˜@€|†L€F”VzÉ5~€(ð ²d € É›2d T À Q“ Te²d,€2dB¢K€ P‚P@ÖFRqÒ}!-óL7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  žÉ“ ±2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ¬™§èј@€|fL€F”VzÉ5€€(ð ²d € Éš²d T À Q“ Te²d,€²dB¡µ€ P‚`@ÖFRpè!4u87777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  Ÿ“ °‡2dÿW@?þ®UÀÿÕÐ?ÿ« ì™§é“ ј@€|ÆL€F”VÉ5~€€(È ²d € >²2—Íi¾(@7777BUFR:Èÿ  ”ÀÁÂÀÁ !!À!Ã!!À!Ã*!!À!ÃÀÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀˆP  ž­“ ±2d]À €Gÿõtÿêè3&@€)û4f Ÿ-“ ‘¥‚²d _@  <Ì™ (€€o¬Œ¤ãê‚D²ÚT7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  ž•“ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«¡ ™§ôј@€|¶L€F”V‚É5x€) ²d € Éš²d T À Q“ Te²d,€²dB¡íÀ P‚à@WÖFRq>ù"%X^7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  Ÿ“ °æ2d dÈD?þ®€ý]«@?ÿW@þ®ƒì™ ÿÕÐ?ÿ«¡ ™§ñ“ ј@€}L€F”VVÉ5…€) ²d € Éš²d T À Q“ Th2d,€ €¾²2‘J©[X07777BUFR¦Èÿ  ÊÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!ÃÁ !!À!à !!À!ÃÀÁÀ¾P  ž½“ °2d-dÈD?þ®€ý]«€?ÿW@þ®ƒà ÿÕÐ?ÿ« ì™§Ý“ ј@€~6L€F”UÜÉ5w€)@ ²d € –L€ÐË&@  P…°@§ÖFRsµ''åt7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  žå“ °#2dÿW@?þ®U€ÿÕÐ?ÿ« Ì™§ØÑ˜@€~6L€F”UüÉ5{€) 2d € .€¾²2‰'I9Ûh€7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  ž‘“ ±2ddÈD?þ®€ý]¬À?ÿW@þ®€ ™ ÿÕÐ?ÿ« ¬™§Ù“ ј@€{vL€F”V~É5ˆ€€)@ ²d € É™²d T À Q“ Te²d,€²dB¢@ P‡@ÇÖFRm-M‘x67777BUFR¸Èÿ  ÖÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!ÃÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀÄP  ›q“ µÜ2dQdÈD?ÿ« ÿW@Ù2 Oð£0€ål™(¬a“ kSè@)dÈ@R²dB¼dÈ¥€D©FªdÈ­@ [h}de 8(ôiÐ: 7777BUFR,Èÿ  ŒÀÁÂÀÁ !!À!Ã*!!À!ÃÀÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀ‚P  žM“ ºû\?ÿ« ÿWAY2 OÀ£0€÷ ™(¬a“ kQà@3dÈ@(|}de 6áz‘ñP5À7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  ž­“ ±2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ¬™§äј@€{¦L€F”V’É5†€€(ð ²d € É™²d T À Q“ Te²d,€²dB¢& P‡àA7ÖFRl(á[K07777BUFRTÈÿ  $ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!Ã>!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀÁÂ!!À!ÃÀÁ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀP  žÁ“ °ú2ddÈD € ™GÿÕÐÿ« U›&@ÇÿêèÿÕÐ-“ #ÿúºÿõt“ Àÿõtÿêè €§ÿõtÿêè¶L€F` ïY2 PZ+&@Ö:¤`€>É*€&@jÉ-P/(€ FL€P–ɲ ɇ·)@P @_YH °;Tt ¸7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  žñ“ ±,2dÿW@?þ®UàÿÕÐ?ÿ« Ì™§í“ ј@€|L€F”VxÉ5…€€) ²d € A >²2ziU07777BUFRLÈÿ  $ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!Ã>!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀ P  ž½“ °×2ddÈD €GÿÕÐÿ« UÇÿêèÿÕГ #ÿúºÿõt“ Àý²d3OzÉHÒ€ Ë™2°`ЖL€P26L€Áj€ y“ DK²d*€ ÆL€ L€C”-PJ#dȈL€ „— (`‚﬌¤Ü/R?ÝàT7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  žÅ“ °ú2dÿW@?þ®UÀÿÕÐ?ÿ«¡ ™§õ“ ј@€{öL€F”V„É5‡€) ²d € E€ >²2^Ö )Ø07777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ž™“ ±Â2ddÈD?þ®€ý]«@?ÿW@þ®€ ™ ÿÕÐ?ÿ« ¬™§é“ ј@€|VL€F”V€É5‚€€) ²d € Éš²d T À Q“ Tf2d,€ G>²2w@ ?è7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  žÁ“ °Ã2dÿW@?þ®U€ÿÕÐ?ÿ« Ì™§ý“ ј@€|L€F”V„É5‚€€) ²d € I>²2jÅI éhÐ7777BUFR@Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀP  žÅ“ ±Â2ddÈD?þ®€ý]«À?ÿW@þ®€ ™ ÿÕÐ?ÿ« Ì™§ý“ ј@€|6L€F”VŠÉ5€€)@ ²d € É›2d T Ì™ ]“ Te²d,€²dB¡ À P0@2dLÜ©@(“}de 6ʱ’¬47777BUFRtÈÿ  ²ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!ÃÀÀ¤P  žá“ °ú2dÿW@?þ®U`ÿÕÐ?ÿ« Ì™§õ“ ј@€|ÖL€F”VtÉ5€€) ²d € ˜²d TN¾²2nLiá€à7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  žý“ ±,2d dÈD?þ®€ý]«€?ÿW@þ®l™ ÿÕÐ?ÿ« Ì™§í“ ј@€}FL€F”V2É5~€€(È 2d € Éš²d T À Q“ Tg2d,€ P€>²2w@ üð7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ñ“ ²¼2ddÈD?þ®€ý]«?ÿW@þ®€ ™ ÿÕÐ?ÿ«¡ ™§ñ“ ј@€|ÖL€F”V€É5‡€(Ü ²d € É™²d T À Q“ Te²d,€ Q¾²2f) 8è°7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  žA“ ±ô2dÿW@?þ®U€ÿÕÐ?ÿ« ì™§á“ ј@€}fL€F”VpÉ5€€) ²d € T>²2c¸ À 7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  Ÿ“ ±,2ddÈD?þ®€ý]«À?ÿW@þ®l™ ÿÕÐ?ÿ« Ì™§ñ“ ј@€}FL€F”VZÉ5€€€) ²d € É›2d T À Q“ Tg2d,€2dB¢K€ PŠ B‡ÖFRpu%(7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  ž5“ ±2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ«¡ ™§ìј@€}D(@F”VtÉ5ƒ€(ð ¡B € Éš²d T À Q“ Tf2d,€²dB¡ PŠÀB—ÖFRneÍ%f­p7777BUFR¢Èÿ  ÈÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!ÃÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀ¼P  ŸU“ ±^2dÿW@?þ®U`ÿÕÐ?ÿ«¡ ™§á“ ј@€}ÖL€F”VNÉ5€€(ð ²d € dšdÈ„,J$ˆ”R€QhVúÈÊ@n¤Áþ`eÀ7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  Ÿa“ °}2ddÈD?þ®€ý]«@?ÿW@þ®ƒì™ ÿÕÐ?ÿ« Ì™§Õ“ ј@€}öL€F”VÉ5‡€(Œ ²d € É™²d T À Q“ Te²d,€ \¾²2|" 8× 7777BUFR–Èÿ  ÄÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!ÃÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀ´P  œ“ ²î!BdÈD?ÿ« ÿW@Y2 P £0€挙(¬=“ júSÀ@RdÈ@°²dBº¥€D Ä©@ dk}de 7⤂{03€7777BUFRXÈÿ  ¢ÀÁÂÀÁ !!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ˜P  žÁ“ °ÿúºÿõt ¯xÿþ®ÿý]dÈ0? ™ŒÀÛ2d4 ´&L€¬XtHÀU“ T²d Td¾²2Wƒí\P7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ž‘“ ±Â2ddÈD?þ®€ý]«À?ÿW@þ®€ ™ ÿÕÐ?ÿ«¡ ™§é“ ј@€{ÆL€F”VˆÉ5ƒ€(Ü 2d € É™²d T À Q“ Te²d,€ k€>²2O_¨øôذ7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  žÙ“ ±2ddÈD?þ®€ý]¬@?ÿW@þ®€ ™ ÿÕÐ?ÿ« Ì™§í“ ј@€{ÆL€F”VtÉ5„€€)@ ²d € É™2d T À Q“ Te²d,€2dB¡íÀ PŽCWÖFRi,ñ &7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  •“ ±ô2dÿW@?þ®VÿÕÐ?ÿ« ì™§å“ ј@€|L€F”VžÉ5}€€) ²d € u€¾²2Fl M(Ð7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  “ ±2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« Ì™§àј@€|6L€F”V–É5€€(´ ²d € É™2d T À Q“ Te²d,€2dB¡íÀ PŽàC‡ÖFRg¯ !е¬7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  i“ ±Â2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ì™§Üј@€|&L€F”V¶É5€€) 2d € ɘ²d T À Q“ Te²d,€²dB¡íÀ P`C—ÖFRhKM"2]¶7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  žI“ ²¼2ddÈD?þ®€ý]«€?ÿW@þ®€ ™ ÿÕÐ?ÿ« ì™§á“ ј@€|¦L€F”VlÉ5‚€€) ²d € É™²d T À Q“ Tg2d,€ |€>²2Yô ­hÐ7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  ží“ ±ô2dÿW@?þ®UÀÿÕÐ?ÿ« Ì™§í“ ј@€}L€F”V†É5ƒ€), ²d € ~€¾²2DËi+¨7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  žÅ“ ²X2ddÈD?þ®€ý]«€?ÿW@þ®ƒì™ ÿÕÐ?ÿ« Ì™§èј@€|ÖL€F”V„É5†€€(ð ²d € ɘ²d T À Q“ Te²d,€²dB¢K€ PPCÇÖFRh1A$ÕJ7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ±“ ±Â2ddÈD?þ®€ý]«@?ÿW@þ®€ ™ ÿÕÐ?ÿ« ì™§Ù“ ј@€}FL€F”V„É5„€), ²d € É™2d T À Q“ Tg2d,€ „¾²2Vlé&ï¨7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  ž©“ ±ô2dÿW@?þ®U€ÿÕÐ?ÿ« ì™§á“ ј@€}ÖL€F”VzÉ5‚€€), ²d € …€>²2C*©,Ö€7777BUFR8Èÿ  ÀÁÂÀÁ !!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀŠP  žQ“ °ÿúºÿõt ¬xÿþ®ÿý]dÈ0? ™ŒÀõ²d4 ³L€¬tM U“ T¤0ýõ‘”€Úý3IÀë7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ž™“ ±ô2ddÈD?þ®€ý]«€?ÿW@þ®ƒì™ ÿÕÐ?ÿ« ì™§á“ ј@€}ÆL€F”VzÉ5€) ²d € É™2d T À Q“ Te²d,€ ‡ >²2AŠ 1¸`7777BUFRfÈÿ  ªÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!ÃÁ !!À!à !!À!ÃÀÁÀžP  M“ ³ 2dÿÕÐ?ÿ« ,™¨(ј@€uöL€F”V"É5x€€)Ì 2d € 9€™2!MR€ 7€6¾²2½ÇHO¯€Ð7777BUFR$Èÿ  †ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÀÁÀ€P  ž=“ ±Â2dÿW@?þ®U`ÿÕÐ?ÿ« ¬™§Ñ“ ј@€}¦L€F”VrÉ5u€€ Š€!>²2M¿ 4](à7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  Å“ ±Â2ddÈD?ÿW@þ®ƒì™ ÿÕÐ?ÿ« L™§Üј@€~(@F”VˆÉ5‚€€), ¡B € 2É™²d° à Q“ Tg2d,€2dB@ B@ P‘DGÖFRlw&úS®7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  ž“ ±2dÿW@?þ®UÀÿÕÐ?ÿ« Ì™§Ù“ ј@€~VL€F”VVÉ5†€)@ ²d € €#¾²2Vlé?Y¨p7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  žu“ ²î2ddÈD?þ®€ý]«@?ÿW@þ®ƒèP€ ÿÕÐ?ÿ« ¬™§Õ“ ј@€}öL€F”VlÉ5‡€€(´ ²d € É™2d° à Q“ Te²d,€ ‘€$¾²2H ©@*p7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  ž “ ±ô2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ì™§àј@€{&L€F”V¾É5€(Ü ²d € ɘ²d T À ]“ Te²d,€²dB ÁÀ P“D·ÖFRgÍÒ“F7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  žU“ ²X2ddÈD?þ®€ý]¬@?ÿW@þ®€ ™ ÿÕÐ?ÿ«¡ ™§á“ ј@€{FL€F”V¼É5ƒ€€) ²d € É™²d T À Q“ Te²d,€ ˜€&>²2.Òhî`€`7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  å“ ²î2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« Ì™§ØÑ˜@€{6L€F”VÐÉ5…€€), ²d € ɘ²d T À ]“ Te2d,€²dB Ô€ P“ D×ÖFRd‡Áìp7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  É“ ²î2ddÈD?þ®€ý]¬€?ÿW@þ®€ ™ ÿÕÐ?ÿ« Ì™§í“ ј@€{L€F”VºÉ5€), ²d € ɘ²d T À Q“ Te²d,€ €)>²2ÈóB€7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  “ ±ô2dÿW@?þ®VÿÕÐ?ÿ« ¬™§Ù“ ј@€{fL€F”VºÉ5€€(  ²d € ž€)¾²2!Í÷ˆ@ð7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ž!“ ±2ddÈD?þ®€ý]«À?ÿW@þ®€ ™ ÿÕÐ?ÿ« Ì™§Ý“ ј@€{¶L€F”VžÉ5‡€) ²d € ɘ²d T À Q“ Te²d,€  €+>²22ž(û1Àp7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  œ]“ ±ô2dÿW@?þ®V`ÿÕÐ?ÿ« ¬™§Ý“ ј@€{¶L€F”V¶É5†€)@ ²d € ¢€,>²2z À!p7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  Å“ ±2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ¬™§Ðј@€|FL€F”V¢É5†€€(Ü ²d € É™2d T À Q“ Te²d,€2dB¡íÀ P”àE·ÖFRer!! e’7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  }“ ²X2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§Ôј@€{¶L€F”VÂÉ5†€€)h ²d € ɘ²df ` ]“ Te²d,€²dB0 ‰€ P”ðEÇÖFRd „­¬7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ù“ ±ô2ddÈD?þ®€ý]¬?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™§Ù“ ј@€|VL€F”V¬É5‡€€) ²d € ɘ²d T À Q“ Te²d,€ ©/>²2,ëé ¬€€7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  …“ ±ô2ddÈD?þ®€ý]«À?ÿW@þ®€ ÿÕÐ?ÿ« ¬™§Õ“ ј@€|–L€F”VœÉ5€(È ²d € L€Áj€ "•ÀFÖFRd‡Á"šˆÂ7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  œ)“ ±ô2dÿW@?þ®VÿÕÐ?ÿ« l™§Ôј@€|¦L€F”VvÉ5‚€) ²d € ²1>²2EéÇè# 7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  žA“ ³è2ddÈD?þ®€ý]«?ÿW@þ®€ ÿÕÐ?ÿ« Ì™§å“ ј@€|–L€F”V˜É5w€€) ²d € L€Áj€ "–pF7ÖFReÚM$  ~7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  ‰“ ±ô2ddÈD?þ®€ý]«@?ÿW@þ®€ ÿÕÐ?ÿ« ì™§Õ“ ј@€|vL€F”V˜É5~€€) ²d € L€Áj€ "–FGÖFRcƒY$[À¾7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  žÁ“ ±ô2dÿW@?þ®U`ÿÕÐ?ÿ« Ì™§Ý“ ј@€}¦L€F”V˜É5Š€(È ²d € ¶€3>²2(OÉ)ÈØ07777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  ›¹“ ´~2ddÈD?þ®€ý]«€?ÿW@þ®€ ÿÕÐ?ÿ« ¬™§Ñ“ ј@€|ÖL€F”VÉ5€€) ²d € L€Áj€ "—FwÖFRciI%®K–7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  ža“ ±Â2dÿW@?þ®U@ÿÕÐ?ÿ« ¬™§Ù“ ј@€}¦L€F”VÉ5}€€(ð ²d € ¼4¾²2“‰:€€7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  “ ´â2ddÈD?þ®€ý]¬?ÿW@þ®€ ™ ÿÕÐ?ÿ«¡ ™§Ù“ ј@€}vL€F”V É5v€(È ²d € ɘ²d T À Q“ Te²d,€²dB¡È@ P—°F·ÖFRe ù&˜«Â7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ž“ ³„2ddÈD?þ®€ý]«€?ÿW@þ®€P€ ÿÕÐ?ÿ«¡ ™§Õ“ ј@€}¤(@F”V¢É5y€(Ü ¡B € ɘ²d° à Q“ Te²d,€ ¾€6>²2,ëé7ž€07777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ž©“ ´~2ddÈD?þ®€ý]«@?ÿW@þ®€ ™ ÿÕÐ?ÿ« ì™§Ù“ ј@€}fL€F”V”É5y€) ²d € ɘ²d T À Q“ Te²d,€ ¿6¾²21Ci7Ò˜P7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ž}“ ´â2ddÈD?þ®€ý]«@?ÿW@þ®€P€ ÿÕÐ?ÿ« ì™§Ý“ ј@€}¦L€F”VŒÉ5~€€) ²d € ɘ²d° À Q“ Te2d,€ À7>²2,ëé9  7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  žu“ ³„2ddÈD?þ®€ý]«?ÿW@þ®€ ™ ÿÕÐ?ÿ« ì™§á“ ј@€}–L€F”VŒÉ5|€€(´ ²d € ɘ²d T À Q“ Te²d,€ À€7¾²2(OÉ:C˜ð7777BUFRÈÿ  ~ÀÁÂÀÁ !!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÀÁÀzP  å“ °ÿúºÿõt ²xÿþ®ÿý]dÈ0? ™ŒÀî²d4 ´öL€«Üt¦Áõ‘”€Ùv“IÈXÀÚ€7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  “ ²X2ddÈD?þ®€ý]¬€?ÿW@þ®€ ™ ÿÕÐ?ÿ« Ì™§Õ“ ј@€}ÖL€F”VŒÉ5€€(x ²d € É™2d T À Q“ Tg2d,€2dB¡ P˜G'ÖFRd(2Óä7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  Ÿ%“ ²î2ddÈD?þ®€ý]«@?ÿW@þ®ƒì™ ÿÕÐ?ÿ«¡ ™§á“ ј@€}ÆL€F”VvÉ5€€(  ²d € ɘ²d T À Q“ Te²d,€ Æ:>²20s FàÀÀ7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ž“ µÜ2ddÈD?þ®€ý]¬?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™§é“ ј@€{fL€F”VØÉ5|€)@ ²d € ɘ²d T À Q“ Te²d,€ È:¾²2ójçÝØÐ7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ž“ ³è2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« ,™§Ôј@€{4(@F”VÖÉ5ƒ€) ¡B € É™²df l™ Q“ Te²d,€²dB0 ‰€ P@2dL!4©@)”y}de 6ÆÃîÐ5 7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  œ“ ´â2ddÈD?þ®€ý]¬€?ÿW@þ®€ ÿÕÐ?ÿ« L™§å“ ј@€{fL€F”VÎÉ5z€€) ²d € L€Áj€ "™ G×ÖFR_ IÛR7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  —É“ µÜ2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§Ý“ ј@€{FL€F”VìÉ5”€€)à ²d € ɘ²d T À m“ Te2d,€²dB ÁÀ Pš HÖFR^!TÈ&7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  M“ ³¶2dÿW@?þ®UàÿÕÐ?ÿ« ¬™§Ñ“ ј@€{†L€F”VàÉ5ˆ€€)T ²d € ÔB>²2ohõç˜ 7777BUFRØÈÿ  äÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ŠdÈ*>vL€Ñ0É“ ÿúºÿõt ±xÿý]ÿúº!B$ÿW@ÿþ®²dŸvL€F”@~É5b²d€)| € € ɘ²d Z À ]“ Te²d,€ Õ€C¾²2í·¨üÒhMp7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  ›ù“ ³è2ddÈD?þ®€ý]¬€?ÿW@þ®€ ÿÕÐ?ÿ« ¬™§Ù“ ј@€{vL€F”VØÉ5p€€), 2d € L€Áj€ "šàH‡ÖFRa`u #Z7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  š©“ ±^2dÿW@?þ®U ÿÕÐ?ÿ«¡ ™§á“ ј@€{ô(@F”V˜É5€)T ¡B € Ù€E¾²2ý. ]è'7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  šÁ“ ±ô2dÿW@?þ®UàÿÕÐ?ÿ« ì™§Ý“ ј@€{öL€F”V¦É5‚€)T ²d € ÛG>²2ój Ÿ@'p7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  ›¥“ ±2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« Ì™§àј@€{öL€F”VœÉ5Œ€(ð ²d € ɘ²d T À ]“ Te²d,€²dB ú P›pH÷ÖFR]NÉ ÒÍx7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  ›å“ °ú2ddÈD?þ®€ý]«À?ÿW@þ®€ ÿÕÐ?ÿ«¡ ™§å“ ј@€|FL€F”VŽÉ5Œ€€)à 2d € L€Áj€ "›ÀIÖFR_¥Á!×8n7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  ˜•“ ±^2ddÈD?þ®€ý]«À?ÿW@þ®€ ÿÕÐ?ÿ« ì™§Õ“ ј@€|fL€F”V’É5‡€€(Œ ²d € L€Áj€ "œIÖFR_ "fsè7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  ” “ ±ô2dÿW@?þ®U ÿÕÐ?ÿ«¡ ™§Õ“ ј@€{öL€F”VŽÉ5z€€)h ²d € âI>²2 I©>ð7777BUFR>Èÿ  ÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀP  ˆdÈ**†L€ÊðÉ“ ÿúºÿõt ­xÿý]ÿúº2d$ÿW@ÿþ®€²dŸ°F”@fÉ5e2d€* € € É™2d° ì™ Q“ Te²d,€²dB@ >€ P@2dL„©@)Å“}de 6¨-º0ÀÀ7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  šÍ“ ±ô2dÿW@?þ®VÿÕÐ?ÿ«¡ ™§Ù“ ј@€|vL€F”V´É5„€€(x ²d € ãJ>²2ω±Ø' 7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  —¹“ ±ô2dÿW@?þ®U ÿÕÐ?ÿ« Ì™§Õ“ ј@€|fL€F”V É5x€)h ²d € åK>²2 +¨2@7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  œ%“ ±^2ddÈD?þ®€ý]«€?ÿW@þ®€ ÿÕÐ?ÿ«  ™§Ñ“ ј@€|öL€F”VlÉ5„€€(x 2d € L€Áj€ "œÀIwÖFR^ïy#æh7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  u“ ±ô2dÿW@?þ®U`ÿÕÐ?ÿ«¡ ™§Õ“ ј@€|öL€F”V”É5€€(Ü 2d € éL>²2ýþi'#À7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  œ¹“ ³ 2ddÈD?þ®€ý]«€?ÿW@þ®€ ÿÕÐ?ÿ« ì™§Õ“ ј@€|ô(@F”V’É5€€€(´ ¡B € L€Áj€ "PI—ÖFR_#%S%<7777BUFRrÈÿ  ²ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ¢P  œ½“ ±ô2ddÈD?ÿW@þ®€ ÿÕÐ?ÿ« ,™§Õ“ ј@€}D(@F”V”É5‚€€(  ¡B € L€Áj€ "pI§ÖFR^˜%šÃD7777BUFRlÈÿ  ¬ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÁÀ¢P  m“ ±ô2dÿW@?þ®VÿÕÐ?ÿ« Ì™§Õ“ ј@€}–L€F”VŒÉ5€€€) ²d € FL€ER€ (;@“o¬Œ¤Ä KëÐä7777BUFRrÈÿ  ®ÀÁÂÀÁÂ!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!ÃÁ !!À!à !!À!ÃÀÁÀ¦P  5#&@@ÿõtÿêèhñÿý]ÿúºÉ` „À €'h$i@bÌ™Vøè¡Àk&@¨Z (A“ Z ( d ³ë#)º¸…t›7777BUFRrÈÿ  ²ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ¢P  i“ ²î2ddÈD?ÿW@þ®€ ÿÕÐ?ÿ« Ì™§Üј@€}$(@F”V¨É5}€(È ¡B € L€Áj€ "ÀIÇÖFRaFm&Æ=¾7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  œu“ ±2ddÈD?þ®€ý]«À?ÿW@þ®€ ÿÕÐ?ÿ« l™§Õ“ ј@€}&L€F”V†É5€€(Œ ²d € L€Áj€ "žI×ÖFR^mA&¥°L7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  ší“ ³„2ddÈD?þ®€ý]«À?ÿW@þ®€ ÿÕÐ?ÿ«  ™§Ñ“ ј@€|ÆL€F”VªÉ5€€€( ²d € L€Áj€ "ž€I÷ÖFR]hÙ'£˜ì7777BUFRfÈÿ  ªÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀžP  “ ±Â2dÿW@?þ®U ÿÕÐ?ÿ« ¬™§Ù“ ј@€}FL€F”V¢É5{€€(  ²d € L€Áj€ "ž JÖFR`!'b}â7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ž “ ³è2ddÈD?þ®€ý]«€?ÿW@þ®€ ™ ÿÕÐ?ÿ« Ì™§Ù“ ј@€}VL€F”V É5y€€(È ²d € ɘ²d T À Q“ Te²d,€ øQ¾²2 ©D˜P7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  šÕ“ ²&2ddÈD?þ®€ý]«À?ÿW@þ®€ ÿÕÐ?ÿ«  ™§Ñ“ ј@€|æL€F”VŠÉ5€€( 2d € L€Áj€ "Ÿ0JGÖFR]®=)xXú7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  šý“ ´â2ddÈD?þ®€ý]­@?ÿW@þ®€P€ ÿÕÐ?ÿ« l™§ù“ ј@€zÖL€F”VÖÉ5€)Ì ²d € ɘ²dr à ]“ Te2d,€ ú€S>²2Ú/¨ßº€% 7777BUFRöÈÿ  öÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀâP  œ]“ µÜ2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« L™§ìј@€{VL€F”VäÉ5‚€), ²d € É™2dr à ]“ Te2d,€²dB@ k€ PŸ`JwÖFR[”Ô« 7777BUFR@Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀP  “ µÜ2ddÈD?þ®€ý]¬€?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§á“ ј@€{¦L€F”VÎÉ5y€€)T ²d € LÉ™²d Z Ì™ a“ Te2d,€²dB ¯ PA²dL H©@*­}de 5¼‚‘Ù°=`7777BUFR&Èÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀøP  ›}“ ´â2ddÈD?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§üј@€{ÖL€F”VèÉ5ˆ€€(Ü ²d € É™²dr l™ ]“ Te²d,€²dB0 Z  PA²dL H©@*®}de 5‹®‘Ý)0HÀ7777BUFR,Èÿ  ŒÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀ‚P  œ¥“ ±ô2dÿÕÐ?ÿ« l™§Ù“ ј@€|L€F”V²É5w€€* 2d € €W¾²2ÈHhñÕè ð7777BUFRšÈÿ  ÆÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!ÃÀÂÀ¶P  ™™“ ±,2ddÈD?ÿW@þ®ƒèP€ ÿÕÐ?ÿ« ,™¨¬Ñ˜@€g&L€F”UxÉ5W€)| ;2d € ÈÉœ2d& € (€ ¬Œ¤¬§J Þ*h7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  ›ý“ ±Â2dÿW@?þ®V ÿÕÐ?ÿ« l™§å“ ј@€{ÖL€F”V¾É5z€€)¤ ²d € €Y>²2ØIHí("ð7777BUFRÚÈÿ  æÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ”Õ“ ·Ð2ddÈD?þ®€ý]­@?ÿW@þ®€P€ ÿÕÐ?ÿ« l™§Ù“ ј@€{6L€F”VœÉ5n€)@ ²d € ɘ²d T À ]“ Te2d,€ Z>²2Ô}höƒØ;07777BUFRÈÿ   ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!Ã>!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀöP  ›E“ ²&2ddÈD€GÿÕÐÿ« U€ÇÿêèÿÕГ #ÿúºÿõt“ Àû²d3O†…HÒ€ Ò2¯€Ð2¤(@P ™26L€Á À ŒDK²d*€ ¦L€ 6L€F”0J€T( lúÈÊ@kCØ£ýÞ’€7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  ˜•“ ±ô2dÿW@?þ®V ÿÕÐ?ÿ« Œ™§Ñ“ ј@€{¶L€F”VºÉ5w€* 2d €  €\>²2ÛÐiÁ¨.Ð7777BUFRŽÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!ÃÁ !!À!à !!À!ÃÀÁÀ²P  œÍ“ ³è2ddÈD?ÿW@þ®€ ÿÕÐ?ÿ« ,™¨ј@€uFL€F”V,É5x€)Ì .²d € 3€™2!¶R€ D<¾²2ÁNh]Q 7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  š“ ³R2ddÈD?þ®€ý]«€?ÿW@þ®€ ÿÕÐ?ÿ« Ì™§Ý“ ј@€|t(@F”V€É5†€*X !B € L€Áj€ "¡àK§ÖFR[È)!|È7777BUFRØÈÿ  äÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  ‘dÈ*:&L€ÓˆÉ“ ÿúºÿõt °xÿý]ÿúº2d$ÿW@ÿþ®2dŸVL€F”@žÉ5_2d€*” € € ɘ²d T À Q“ Te²d,€ ]¾²2ÌZ ¹ÀR7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  –Å“ ³ 2ddÈD?þ®€ý]«€?ÿW@þ®€ ÿÕÐ?ÿ« ì™§Ù“ ј@€{öL€F”VšÉ5{€€(ð ²d € L€Áj€ "¢@K×ÖFRYóm"€}¤7777BUFRDÈÿ  –ÀÁÂÀÁ !!À!à !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  B„*9vL€ÇÐÉý]ÿúºW€<ÿW@ÿþ®²dŸvL€F”@fÉ5]!B€)¤ € € _¾²2Ó­ ±ØS7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  ™-“ ±,2d dÈD?þ®€ý]«@?ÿW@þ®€ ÿÕÐ?ÿ« l™§Õ“ ј@€|vL€F”VhÉ5†€(< ²d € L€Áj€ "¢ LÖFR\~u#d[–7777BUFR8Èÿ  ÀÁÂÀÁ !!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀŠP  ™ý“ °ÿúºÿõt ­xÿþ®ÿý]dÈ0>Ì™ŒÀݲd4 ´vL€¬tC )“ T¨¬õ‘”€×HûDÁL7777BUFRØÈÿ  äÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÀÂÀÖP  B„*?FL€×pÉ“ ÿúºÿõt ®xÿý]ÿúº2d$ÿW@ÿþ®²dŸfL€F”@„É5e!B€) € € ɘ²d T À Q“ Te²d,€ €a>²2ÌZ +¨MÐ7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  “¡“ ±ô2dÿW@?þ®V@ÿÕÐ?ÿ« L™§Ù“ ј@€{æL€F”V‚É5z€€) ²d € a¾²2ƧÉÇè@ 7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  –“ ±ô2dÿW@?þ®U€ÿÕÐ?ÿ« ¬™§Ñ“ ј@€|FL€F”V¨É5x€*l ²d € b>²2Ï›i%ƒ8P7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  šy“ ±ô2dÿW@?þ®UàÿÕÐ?ÿ« ,™§Õ“ ј@€|(@F”VŠÉ5ˆ€€(  ¡B € €b¾²2èÕ©&ï¨)`7777BUFRŒÈÿ  ¾ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!ÃÀÀ°P  ™Y“ ²X2ddÈD?þ®€ý]«€?ÿW@þ®€ ÿÕÐ?ÿ« Œ™§Ñ“ ј@€|&L€F”VœÉ5†€(Ü ²d € L€Áj€ "£pLgÖFR[ó…%,Ž7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  —ù“ ±ô2dÿW@?þ®U ÿÕÐ?ÿ« ì™§é“ ј@€|L€F”VÆÉ5w€€)T ²d € €c¾²2ˉ©)`¨1 7777BUFR6Èÿ  ŽÀÁÂÀÁ !!À!à !!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀŠP  dÈ*;æL€À#ÿêèÿÕÐ*´ãÿúºÿõt “ Àû2d4  ³¦L€«1“ tM TT¨ø!õ‘”€ÖMIz8‰7777BUFRFÈÿ  ˜ÀÁÂÀÁ !!À!Ã!!À!ÃÀÁ !!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁÀP  —Õ“ ±ô2dÿW@?þ®U ÿÕÐ?ÿ« Ì™§å“ ј@€|&L€F”VºÉ5u€€*¼ 2d € €d¾²2Ñ< 0˜1p7777BUFRÈÿ  ÀÁÂÀÁ !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÀÁ 3!!À!ÃÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  —q“ ²î2ddÈD?þ®€ý]¬?ÿW@þ®€ ™ ÿÕÐ?ÿ« l™§Ù“ ј@€|FL€F”V¤É5x€€(< 2d € ɘ²dr à Q“ Te2d,€²dB@ \€ P¤L§ÖFR[`&J‹d7777BUFRÈÿ  ÀÁÂÀÁ !!À!à !!À!Ã!!À!Ã!!À!ÃÀÁ !!À!ÃÁÂ!!À!ÃÁ ?!!À!ÃÀ =!!À!ÃÀÁÀÁ !!À!à !!À!ÃÁ !!À!à !!À!ÃÀÁ !!À!à !!À!à !!À!à!!À!à!!À!à!!À!ÃÁ !!À!à !!À!à !!À!ÃÀÁÀðP  dÈ*&öL€ÓˆÉ“ ÿúºÿõt °xÿý]ÿúº2d$ÿW@ÿþ®2dŸvL€F”@JÉ5k2d€)à € € ɘ²d T à Q“ Tf2d,€²dB@ 5 P¤ L·ÖFRY4i&k š7777dballe-7.7/extra/bufr/pilot-gts2.bufr0000644000175000017500000000104412652630043014500 00000000000000BUFR$N€Ó Ù ÿÿ¬D  €„É2„A…ÚÇüÍÿÿÿÿÿÿÿÿÿÿÿÿý~^û>^dzÀð=”ÐÑ鲪‡‰¦ßÿÿÀ€BCÿÿÿÿÿÿÿüwÁkÿÿøçîÿÿÿÿÿÿÿ„ø2ÿÿ<ÒÿÿÿÿÿÿÿðïOÿÿà@•õÿÿÿÿÿÿÿýÿá-ÿÿüòZ¿ÿÿÿÿÿÿÿü¿ÿÿG—ÿÿÿÿÿÿÿù—ÿÿð ÈzÿÿÿÿÿÿÿþÿðFÿÿþy_ÿÿÿÿÿÿÿã¾_ÿÿÀ€›ÿÿÿÿÿÿÿücÀ{ÿÿøã>ÿÿÿÿÿÿÿ}xÿÿ<]/ÿÿÿÿÿÿÿó/ÿÿà@ŠÉÿÿÿÿÿÿÿþàeÿÿüñJ?ÿÿÿÿÿÿÿÂ| ¿ÿÿ'ÿÿÿÿÿÿÿ÷‡çÿÿð Ä’ÿÿÿÿÿÿÿþÿðFÿÿþx‡ÿÿÿÿÿÿÿÞ¾_ÿÿÀ€£ÿÿÿÿÿÿÿü;Á@ÿÿø€ÿÿÿÿÿÿÿÿÿÿÿÿÿð7777dballe-7.7/extra/bufr/generic-bug20140326.bufr0000644000175000017500000000020612652630043015504 00000000000000BUFR†Èÿÿè €ÂÀDgeneric @S^H™X]]Y[Ý][Ûˆ A3˜¬ƒø7777dballe-7.7/extra/bufr/temp-gtscosmo.bufr0000644000175000017500000000026612652630043015302 00000000000000BUFR¶N€Õ Ù ÿÿ¬Œ   €„É4„A…lÅ|Õÿÿÿÿÿÿÿÿÿþ¡éâ?þ^û>^Ç«ðð=ªT¡èîÈ—‡”<<µÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ€xWžJöÿÿÿÿÿÿÿþ¤»é¾ðŒÿÿþ ÿÿÿÿÿÿÿÿÿÿÿÿü7777dballe-7.7/extra/bufr/temp-gts3.bufr0000644000175000017500000000117212652630043014321 00000000000000BUFRz[  €É4R"nÿÿÿÿÿÿÿÿˆ¨“ìàW˜¿Âx3ÀšÿÿÿÿüÿÿÿÿáðÀ¿ÿìÿÿÿÿÿÿÿÿÿÿÿûè'ÿÿÞÿÿÿÿÿÿÿÿÿÿÿûÔ/¿ÿÑÿÿÿÿÿÿÿÿÿÿÿûü;ÿ†Àÿÿÿÿÿÿÿú“Šzÿÿÿÿ½ÿÿÿÿÿÿÿÿÿÿÿü82ÿ‡¦ÿÿÿÿÿÿÿÿúšjl¿ÿ“ÿÿÿÿÿÿÿÿÿÿÿÿü$¿ÿ†ÿÿÿÿÿÿÿÿú*v/ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÔ!¿ÿvÿÿÿÿÿÿÿÿÿÿÿÿûü%ÿoÿÿÿÿÿÿÿÿÿÿÿü$!¿ÿfÿÿÿÿÿÿÿÿÿÿÿÿü!¿ÿ]ÿÿÿÿÿÿÿÿÿÿÿÿü8"ÿÿ†Xÿÿÿÿÿÿÿúž*…/ÿÿÿÿTÿÿÿÿÿÿÿÿÿÿÿü8ÿKÿÿÿÿÿÿÿÿÿÿÿûèÿÿ9ÿÿÿÿÿÿÿÿÿÿÿû¬ÿ3ÿÿÿÿÿÿÿÿÿÿÿûèÿ-ÿÿÿÿÿÿÿÿÿÿÿü8ÿ'ÿÿÿÿÿÿÿÿÿÿÿÿü`&¿ÿ"ÿÿÿÿÿÿÿÿÿÿÿÿü`!¿ÿÿÿÿÿÿÿÿÿÿÿÿÿü%ÿÿÿÿÿÿÿÿÿÿÿÿü%ÿ ÿÿÿÿÿÿÿÿÿÿÿÿûÔ3¿ÿÿÿÿÿÿÿÿÿÿÿÿûÀ7ÿ‡ýÿÿÿÿÿÿÿÿúšj„‹À;@7777dballe-7.7/extra/bufr/ed4.bufr0000644000175000017500000203261012652630043013155 00000000000000BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@0$’I$’JI$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’Im¶Ûm¶Ûm¶Û¶Ûm¶Û`Šˆd)Ž„©iRØ×>”é[\ÈS S_Êt­®ˆd)Ž„©lkŸÊt­®ˆdc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUUUUUUUUUUUUUUUUUUUUUUUPUUð `= 0Ô7 ‚±²| 5˜–ÃçïI—=bUÌtPtPb$øçïÕŸ€± Žçï Ž Žô$çïçï=b ŽÃYáÔ€€,€¤Ë€±€çïb€…ô}ÕøÕøtP±YÕø¥$½ŽÕø½Žn6=b1-=b=bI—UÌn6tPbn6n6UÌÃ$ø€…n6=b=bn6Œº½Ž½Ž˜ïn6I—=bUÌ=bà ŽÉj€áÔY ŽYI—Œº1-Y½5€˜–€s÷€Us$Ÿ 57 s€…‚7 € 5 5$Ÿa¨€,€€,€I> 5j$Ÿ$Ÿ0Ô0Ô 5I>ú—€…ú—‚7 €jç˜ïtPb$øÕŸ1-=b7777BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@(0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶àŠøFS¥mpC!Lt%MsáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð a€…±YŒºUÌ=b=b=b1-1-I—çïUs= g€¤Ë€çïb=bb Ž Žô$ô$çïY$øb1-YÉj€çïÉj€Œa€= I>I>I>I>˜–€ÕŸYÕŸ€ÕŸ€±€¤Ë€±€¤Ë€±€½5€ÕŸ€Œa€Us0Ô= $Ÿ 5ú—ú—‚7 ú—€I>½5€ô$ÃÉj€¤Ë€½5€½5€½5€çïçï Žçï¤Ë€Œa€I>= 0Ô 5±²}ú—€…‚7 ‚7 €Usô$n6ÃÉj€±€ÕŸ€ÉjÃô$çïI—n6b1- Žô$ÕŸ€±€g€Œa€±€˜–€ÕŸ€áÔ Ž1- Žô$1- Žb ŽáÔ€ÕŸ€áÔ€ÕŸ€½5€½5€ÕŸ€ÕŸ€½5€½5€7777BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@@0I$’I$’I$¤’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Ж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUQUUUUUUUUUUUUUUUUUUUUUUUUUð `¤Ë€½5€Œa€€,€€,€˜–€¤Ë€Éj€Éj€ÕŸ€áÔ€ÕŸ€áÔY Ž1-UÌI—=bô$áÔ€±€Œa€€,€g€½5‚±²|0Ô±$øtP½Žb€…tPbtPUÌŒºÉÃ½Ž±YÕøîbŒºbÃáÔ€áÔ€½5€ô$ÃÉj€½5€ô$çïÕŸ€ÕŸ€áÔ€ÕŸ€Éj€ÕŸ€¤Ë€g€I>I>0Ô= Usj0Ôa¨a¨± Žn6˜ï€…I—tPUÌáÔ€ô$ ŽUÌbn6tPbn6I—1-s÷€I>g€g€Œa€I> Ž1-UÌI—bn6I—1-UÌbbtPn6UÌI— ŽÕŸ€½5€¤Ë€Œa€$Ÿ 5jŒa€ÕŸ=b€…n6UÌ7777BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@T0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¹$’I-¶Ûm¶Ûm¶ÛvÛm¶Û`ж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÇÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUTUUUUUUUUUU@UUTUð aI—=bUÌUÌ$ø$ø=b$ø ŽYYçï±€s÷€I>$Ÿ 50Ôs÷€½5€çïáÔI—=bÉj€½5€˜–€±€ô$=b1-I—1-=bô$s÷€g€0Ô7 €…€…€Œa€…‚7 ‚7 €= = I>= I>0Ôg€½5€çïô$$øI—Ys÷€= $ŸjjUs€,€çï$ø Žçï$ø1-ÃÃY Ž$øÃ Ža¨Œa€˜–€Œa€0Ôg€I>$Ÿ7 €O€O€O€O€Œa€…‚±²|Us±€˜–€Œa€€,€˜–€¤Ë€Éj€áÔ Žô$ÕŸ€s÷€j+Ä}ú—€…€Os€O€Œas€Œa‚±²|Uss÷€I>I>0Ô= Us7777BUFR&bÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊBUUUUU]kZÖµ­k{Þ÷½ï{Þ÷½ï{Þ÷½ïœç9Îsœç9Îsœç9Îs½ï{Þ÷½ï{Þ÷½ï{Þ÷Þ÷½ï{Þ÷½ï{Þ÷½ïxŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*\#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUUTUUUUUUUUUTUUUUð `g€½5€¤Ë€0Ôa¨0Ô 5±²}s€…ss€O€Œa€I>0Ô= ½5€ÕŸ€˜–€€,€˜–€˜–€˜–€± Žô$Ã$ø=b$ø=bI—bI— ޽5€UsI>s÷€€,€±€±€±€˜–€˜–€Œa€˜–€0Ôa¨g€$Ÿj 5±²}ú—€…ú—ú—€…€Œa€…€Œas‚±²~±²~±²| 5 5$Ÿ= = 0ÔUs˜–€Éj€±€Œa€s÷€áÔ€áÔ€˜–€½5€a¨I>a¨ÕŸY=b$øYÉj€½5€Éj€ô$$øÃ$ø ŽUÌ=bô$Éj€g€0Ôú—€Œass€I>Éj€çïÕŸ€˜–€½5€±€s÷€s÷€Us0Ô0Ôa¨ 5$Ÿ= 7777BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠ!¦:¦¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUTUUUUUUUUUUUUUUUUUUU `jjOX€Œa ŽŒº‚²ô}=bI—1-€…I—hUÌ[æ[æ[æ[æ1-äˀŒa€[€g€¤Ë€Ûº˜–€Œa€¤Ë€€,€˜–€½5€½5€˜–€çïÃ=b¤Ë€Éj€OX€jZ~6â-hhh‚™H|0Ô€,€Éj€€,€Œa€˜–€¤Ë€Œa€€,€˜–€Ï…çï1-I—ÃÃÛº$ø1-1-ÃÃÃÉj€€,€˜–€Éj€½5€Ï…Ï…YÃ1-ô$=b ŽI—=b=bÃ1- Ž ŽÛº˜–€[€j 5I>I>= OX€[€OX€s÷€[€g€[€Œa€¤Ë€Éj€Ï…ÃÃY ŽYs÷€€,€[€Œa€±€Ûº½5Y1-˜ïèH7777sBUFR¶bÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€0’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹)Ò¶¸!¦:¦¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð _“‡' Ç|RH6+0`!`˜–$øc dpŒ0&% [€ªæ1-1†Ä¤ $ŸUsŒa Žé1†Ið?xÐ#`$Ÿ€,‚“à ë\À1—Pc. ÀBÁ=b’ÕV~¤~ð:] ˜– ŽéV~é¬?x 'À€jj† Æ\À.ŠlV`ž±$øbZ“à¡ Ö -ÆÀlV`ÀBÁn6Ül&\¬ü&% LK@Œa$øzÄ&\ ®`B@„€9ûÀpê@ÕŸ«?%ªKTH!‘À9ûÀpê@áÔzk1† @?x 5ð 0ÔUsªæ²&\~ð™p#`F0Às÷€Ï…²d?xŒ09ûÀLK@Œab1†Ÿ¼€€€ 57777 BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€40$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èKçÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUUUUUUUUUUUUUUUUUUUUUUUUýàb¥}|$Ÿ˜–€g€$Ÿjj 5 5 5j 5= 0ÔI> 5 5¥}}tPtPtPîbtPîb€0ÔUsI>= Us[€[€g€s÷€s÷€Œa€€,€Œa€Œa€Œa€g€[€Us0Ô0Ô0Ô0Ô[€s÷€s÷€Œa€Œa€¤Ë€ÕŸ€çï ŽYUÌ=b¥$Œº=bÃÃ1-ô$Éj€½5€˜–€˜–€Œa€˜–€¤Ë€±€çïÛº$øÃ1-$ø$øUÌ=bUÌI—=b=bÃÃô$ÃÃYY Ž Ž$ø1- Ž ŽYYÃ Ž Ž Ž1-I—=bI—1-1-Yô$ÕŸ€€,€Éj Žô$UÌŒº€…tPŒºâ-èH7777sBUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€H0 $’I$’I$’RI$’I$’I$›m¶Ûm¶ÛrI$’Km¶Ûm¶Ûm¶Ý¶Ûm¶Û`ŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2cŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUTUUUUUUUUð bîbâ-½ŽÕøîbÕø½ŽŒºn6UÌ$øI—UÌbn6n6¥$˜ïÕøÕø±YbÃ1-I—n6˜ï˜ï¥$½Ž˜ï±YtPtP˜ïn6tP˜ï=b¤Ë€s÷€a¨a¨I>UsI>= = I>g€áÔ=bI—I—n6n6U̘–€a¨$Ÿs÷Yô$¥$½ŽtPtP‚=»I—b1-n6±Y‚²1-YÃô$=b$ø=b=b½5€s÷€= 0Ô0Ô±²+Ä+Ä|$ŸUs˜–€±€˜–€±€áÔ€áÔYÃn6tP1- Žô$çïÉj€€,€= = $Ÿjja¨¤Ë€çïçïÕŸ€ÕŸ€áÔ€çïô$ÕŸ€7777sBUFR&bÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê‚UUUUUU[Þ÷½ï|cÆ1ŒcÆ1ŒcÆ1Œç9Îsœç9Îsœç9ÎskZÖµ­kZÖµ­kZÖµ­ï{Þ÷½ï{Þ÷½ï{Þ÷°‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUU@UUUUUUUUUUð `çï1-1-I—btPn6 Ž= €, ŽçïáÔ€Éj€Éj ŽÃçïÉj€½5€ô$ô$çïçïYáÔ€½5€½5€çïÃà Žô$ ŽáÔ€g€= s÷€±€˜–€áÔ1-=b1- Žô$çïçïÃô$ÃYáÔ€çïáÔ€ÕŸ€ÕŸ€ô$˜–€j7 €…€…‚±²~±²|0ÔI>g€a¨Usg€a¨ŒaYÕŸ€½5€½5€½5€€,€$Ÿ±²}ú—‚±²~7 €g€½51-UÌYŒa€±€ÕŸ€çïô$áÔ€Éj€½5€Éj€½5€Œa€g€g€g€0ÔI> 5= = €,€áÔ1-ô$ÃYô$çïçïô$1-UÌUÌ=b=bô$Y±€7777BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠˆd)Ž„±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUAUUUUUQUUUUPUð `g€0Ôj0Ôa¨Us˜– ŽI—UÌáÔ€ÕŸ€ÕŸ€çï$øŒº˜ïô}ÉÀ…UÌ1-˜–€g€s÷€Us0ÔUs˜–€áÔ€çï±€ÕŸ€ç€½5€¤Ë€€,€½5€ô$YYY1-1-UÌ=bô$Œa€€,€±€ô$ÕŸbb1-ÕŸ€ô$½5€½5$øI—1-$øáÔ€½5€½5€s÷€I>= jj$Ÿ+Ä~±²|jI>UsI>a¨Usa¨s÷€ÕŸ€Œa€˜–€˜–€¤Ë€½5€¤Ë€áÔ€ÕŸ€s÷€UsUs0Ô±²|$ŸUss÷€s÷€g€Us€,€Œa€g€a¨¤Ë€g€˜–€¤Ë€g€€,€0Ôj€…ú—ú—€…ú—ƒ+Ä|= ÕŸI—Ã7777 BUFR¶bÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¦5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]’Õ²&\H:5gà†GI—zÄdKTÆ ®`ð O€ @ 5/M`dµ@±I—1†>Æ øP#`LK@Éj«?bZd€ 5jj0Ô† |(™pF0À˜–UÌ1†Ÿ¼dp\À,@ F0Àž±UÌ«˜õˆÆ ÓXð *¹€$Ÿa¨dÐ-ÆÀX€@˜–€ÕŸbôÖ&\ –¨™p5gàªæ½Žƒb³c¾ q°O€#`9ûÀ^šÀg€çïÏÞd L¸:= ^šÀ¤ËYbZ&\Hýà9ûÀzçïÄW0 L¸ã`)2à/M`0ÔUsI>ô$ @ ýà8u LK@ŒaYÏÞ @|( øPð ReÀ½5€7777€0BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ00’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðU@UUUUUUUUUUUUUUUUUUPUUUUUUð `˜–€g€I>= j+Ä~±²~7 sss€…€…€…ú—€j+Ä| 5 5 5j$ŸUsa¨g€g€I>a¨g€$Ÿ 5j0Ô0Ô 5€,€˜–€Us= 0Ô$Ÿ$Ÿ0Ô= g€ç€UsI>0Ôs÷€a¨0Ô0ÔUs= Uss÷€áÔb¥$€…n6ÃÉj€áÔ€ô$ô$Ã$øáÔ€˜–€s÷€s÷€Us+Ä~±²~7 ‚±²|Us±€¤Ë€ÕŸ€Œa€= UsI>0Ô0ÔUs€,€¤Ë€a¨g€= I> 5ú—€…€…€…sú—€Us±€¤Ë€Œa€a¨Usg€a¨Us˜–€ÕŸÃYbŒºU̽5€€,€a¨a¨I>I>a¨7777 BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀH0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS [çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUPUUUUUUUUUUUPUUUUUUUUUTUð `¤Ë€ô$=bn6I— Žô$çïô$I—$øÕŸ€ÕŸ€ô$Œa€€,€s÷€˜–€UsjI>j7 ú—€ 5= ˜–€˜–€s÷€Usg€s÷€a¨a¨UsI>˜–€áÔ€ÕŸ€áÔ€½5€¤Ë€˜–€s÷€Us$Ÿj$Ÿ= 0ÔUs= UsI>0ÔUsg€¤Ë€ÕŸ1-UÌn6Œº$øÕŸ€˜–€Œa€I>ú—€Œa€…€$Ÿ¤Ë€ÕŸ€a¨$Ÿ$Ÿ0Ô$Ÿ€,€½5Y˜ï½Ž±YtP1-Ã$øY¤Ë€€,€= jI>I>Œa€çï½5€Éj€˜–€˜–€½5€áÔ€ô$Yçï¤Ë€g€a¨$Ÿ7 s€…€…ú—ƒ+Ä|0Ôa¨UsUsj0Ôj7777 BUFRbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÂLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ\0 $’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶ÐŠçÂ2+k€d)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðB!B„!B„!!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!`€,€€,€Éj€˜–ƒ“†ÿtþŸcbZèHn6ô$ô$èHŒa€çïçï½5€½5€˜–€˜–€Ï…Éj€±€ô$I—½Ž±Y‚²±YY$øÉj‚Ÿcn6ô$n6tüŒa€ô$Yô$Ï…¤Ë€Ï…Ûº=b=b=b$øI—=b1-çïÏ…Éj€½5€±€˜–€Œa€¤Ë€Ï…1-I—O±=b=b[æÃ$øô$Ã[æO±h‚²äˀ€,€Œa€½5tP˜ï¥$¥$tP€ô$½5€±€˜–€€,€¤Ë€Œa€¤Ë€¤Ë€Éj€½5€½5€Éj€¤Ë€±€€,€˜–€g€g€˜–€˜–€±€çï ŽÕø‚ ç˜ï½Žh$ø Ž Ž Ž ŽO±=b1-Y½5€±€s÷€€,€7777$BUFR&bÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÂUUUUUUUUUUUUUU^sœç9Îsœç9Îsœç;Þ÷½ï{Þ÷½ï{Þ÷½ï}ï{Þ÷½ï{Þ÷½ï{Þ÷€„!B„!B„!D!B„ Šˆd)Ž…±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUPUUUPUUUUUUUUUUð b7 ‚7 €…€…ú—€0Ô±€Éj€s÷€I>UsUs€,€˜–€˜–€€,€½5€ÉjI—Ã$øô$áÔ€€,€ 50Ôg€áÔ Žô$½5€˜–€áÔ€áÔ€ÕŸ€áÔ€½5 Žô$g€= 5 5 5+Ä~7 €Œa€…€ 5I>˜–€s÷€a¨0Ô= $Ÿ= = a¨˜–€g€s÷€Éj€I>±²~7 ú—€…€…ú—€…s€…ú—€ 5= I>$Ÿ$ŸI>= jUs$Ÿ0Ô 5 5$Ÿ±²}€…€Œa€…ss€…‚7 €= g€$ŸI>a¨I>= Us0ÔI>Usj= €,€¤Ë€= 0Ôj±²~7 ƒ+Ä|g€˜–€s÷€0ÔI>7777BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê 0’I$’I$’I%$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èRØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UTUDUUUUEUUUUUUUUUUUPUUUUð `j$Ÿ0Ô= UsI>j0Ô0Ô= jUs0Ô±²}ss€O€O€…s€ 5= 5= I>= +Ä~±²+Ä}ú—‚7 €$ŸI>$Ÿ= 7 €j+Ä+Ä| 5jUss÷€˜–€¤Ë€Œa€s÷€I>0ÔI>½5€Uss÷€€,€Éj€áÔ€s÷€I>= +Ä|j$Ÿs÷1-Ã1-±€˜–€±€Œa€¤Ë€Œa€ÕŸ€ÕŸYYb€…bÃÃYÉj€€,€I>g€Œa€Éj€ÕŸ=b$øáÔ€±€½5=bô$ ŽYô$ÃYô$Éj€±€s÷€I>j0Ô±²~±²|j¤Ë€ô$Y¤Ë€Us±€çï½5€çïçï¤Ë€˜–Yn6Ã7777>BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê 0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUU@UUUUUUUUUUUUUUUUUUUUEð `0Ôa¨0Ô 5€…s€…‚±²|a¨Usa¨a¨I>a¨g€ô$€,€I>g€a¨Œa€I>$Ÿ 5j 5= $Ÿ€…€Œa€Œaú—€g€ 57 ‚7 ‚7 ƒ+Ä| 5j 5$Ÿ0ÔUsj$Ÿa¨¤Ë€I>$ŸÕŸƒ+Ä~7 s€ÕŸ˜ïÃÃ$ø˜ïŒºUÌ€…UÌâ-‚=»â-îbîb‚ ç1†bZô}±Yâ-îb±Y˜ï˜ï˜ïîb‚²¥$˜ïŒºn6bb1-n6bn61-±€g€a¨g€g€Usj 5= ˜–€ÕŸ€áÔ€¤Ë€Œa€Œa€Œa€Œa€˜–€¤Ë€Œa€€,€½5€Éj€ô$$øáÔ€˜–€Us0ÔI>0Ô+Ä|$Ÿs÷€7777>BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê80 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUAUUUUUPUUUUUUUUUUUUUð `½5ÃYçïáÔ€Éj€Œa€½5€Œa€¤Ë€¤Ë€g€g€s÷€g€a¨a¨$Ÿj$Ÿ 5$ŸŒa€½5€ô$Éj€½5€Œa€g€¤Ë€s÷€a¨g€g€g€g€a¨€,€€,€s÷€= I>I>€…‚7 €ja¨±€ÕŸ€±€˜–€Œa€g€€,€€,€s÷€g€= = ±btP=bÕŸ€s÷€ô$½5€ss‚7 ú—€…€$Ÿs÷€I>Usg€I>$ŸUsg€= I>Œa€€,€0Ô 5jUsUs±1-€…1- ŽÉj Ž Ž¤Ë€çîb‚ 罎Œºô}ÉñY˜ïI—$ø€,€a¨a¨˜–€çï1-UÌ=b Ž=bUÌ1- Ž7777>BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊL0 $’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUTUUUUUUUUUUPUUUð `ÉjY$ø$ø˜ïŒºtPn6bI—çïÕŸ€±€g€˜–€áÔ$ø=bô$ÃÃÕŸ€±€Éj€½5€ô$YI—ÕŸ€¤Ë€¤Ë€˜–€€,€¤Ë€Œa€I>a¨$øçïáÔ€ÕŸ€½5€˜–€±€Œa€±€Éj€çïÉj€g€ô$1-I—Éj€€,€I>I>j+Ä|0Ô±€ÕŸ$øÕŸ€ÕŸ€±€Œa€±€ÕŸ€Éj€˜–€½5€¤Ë€€,€ô$áÔ€g€I> 5±€= g€a¨¤Ë€g€€,€Œa€s÷€s÷€áÔ€¤Ë€¤Ë€Œa€Œa€Œa€0Ôj+Ä}ú—sú—€…ú—ƒ+Ä~±²~±²~7 €= 0Ôj+Ä|$Ÿja¨0Ô½5€áÔäˀ€,€Us7777>BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Êd0I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž…±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUAUUUUPUUUUUUUUUUQEUð b±²|0Ô0Ôg€¤Ë€½5€±€˜–€˜–€€,€€,€˜–€±€Éj€ô$çï½5€€,€€,€€,€$Ÿ+Ä}€…€…‚±²}ssƒ+Ä|s÷€ÕŸ€ç€¤Ë€€,€€,€s÷€ŒaÃÕŸ ŽáÔ€¤Ë€ÕŸ€Us±²}ú—€ 5+Ä~±²+Ä|g€g€½5€a¨I>UsI>a¨g€I>I>a¨a¨g€Œa€g€a¨= sƒ+Ä}ú—ú—€jI>Usa¨= = $ŸI>Us= I>I>= s÷€½5€Éj€çïÕŸ€¤Ë€±€Œa€a¨I>g€±€Éj€çïg€½5€±€Œa€€,€˜–€€,€˜–€ŒaÃbtPUÌÕŸ€Éj€Us+Ä|Us 5±²|= I>˜–€g€€,€7777>BUFR&bÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊUUUUUUUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï@„!B„!B„!D!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œc!B„!B„!@Š¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@U@@UEUUUUUUUUTUUUUUð `s÷€˜–€€,€¤Ë€a¨s÷€g€a¨a¨½51-¤Ëƒ+Ä~7 ú—ƒ+Ä~±²|j= a¨0Ô+Ä|Œa€…€…ú—ú—€…‚7 €…ƒ+Ä~7 € 5g€0Ô$Ÿ$Ÿ+Ä+Ä~7 €…€…€…‚±²|7 ‚7 ú—s€…s€…€…‚7 ƒ+Ä+Ä|$ŸUs0Ô$Ÿj+Ä|±²+Ä| 5I>Œa€¤Ë€Éj€½5€¤Ë€±€ô$ÕŸ€áÔ€±€½5€Œa€€,€˜–€Usú—ú—€…€…€0Ô€,€½5€˜–€˜–€€,€s÷€g€˜–€s÷€˜–€¤Ë€€,€a¨I>= Us$Ÿ$Ÿ+Ä|0Ô= = 5$Ÿs÷€Œa€˜–€¤Ë€Éj€çï=bà ŽáÔ€áÔ€Éj€½5€g€a¨7777BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛnÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUTUUUUUUUUUUUUUUUUTUUU@ð `I>0Ô0Ô 5±²~7 ‚7 ‚±²|$Ÿ¤Ë€áÔ€½5€s÷€Œa€½5€ÕŸ€½5€½5€˜–€€,€áÔ€±1-UÌŒº˜ïäˀg€0Ôj±²| 5jÉj1- Žçïô$Œa€Éj€ô$Y=b1-ÃÃI—UÌbI—$ø1-Éj€€,€= I>I>g€€,€˜–€Œa€$ŸI>Us$Ÿ$Ÿ0ÔI>$Ÿ¤ËYçïŒaYÕŸ€I>a¨ô$çïÉj€çïÃI—ÕŸ€g€Œa€I>áÔ€˜–€€,UÌb$øa¨g€Œa€Us$Ÿ7 ú—ƒ+Ä~7 ‚7 ‚±²~7 €Usa¨= 0Ôa¨I>= 0Ôa¨s÷€= = 0Ô= 0Ô+Ä~±²}ú—‚7 ú—‚7 €7777 BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@,0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUPUUUUUPUUEUU@UUUUð `= ¤Ë€áÔ€˜–€g€I>0ÔI>Usa¨g€a¨I>I>Us$Ÿj 5j$Ÿ0ÔI>g€¤Ë€Œa€a¨Usa¨Ãb˜ï$øÃUÌY€,€ÉjÉÃÕø½ŽtPI— Žj+Ä+Ä|g€çïÕŸ€a¨I>$Ÿ 5 5j 5$Ÿ$Ÿ$Ÿj$Ÿ0Ôjj$Ÿ0Ô€…‚7 €0ÔUsI>= 0Ô$Ÿ$Ÿ+Ä| 5$Ÿ0Ô= Us= 0Ô0Ôjj±²}ú—s€…€$ŸjI>a¨I>Us= I>= g€Usj˜–€˜–€0Ô+Ä~7 €Œass€O€Œa€…‚±²|= Œa€Us= $Ÿ= 0Ô7777 BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@@0$’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@UUUUUUUUUAUUUUU@UUUU@UUUUð `a¨a¨g€a¨0Ô 5jú—€Œa€Œas€Œa€Osƒ+Ä|= a¨UsUsUs= $ŸI>Usa¨a¨= 0Ô= g€a¨j$Ÿ$Ÿ 5= áÔ€áÔ€çïÕŸ€Éj€¤Ë€€,€Œa€Usg€€,€€,€Us= I>I>= 5ú—‚7 € 5$ŸUs½5UÌbçï€,€±€˜–€s÷€€,€Usg€˜–€a¨I>= 5= ú—‚7 ‚7 sú—ƒ+Ä|a¨Éj€áÔY½5€˜–€¤Ë€±€áÔ€áÔ€ÕŸ€±€€,€I>= j0Ôj±²+Ä~±²}ú—ú—€…ƒ+Ä|= s÷€g€€,€g€˜–€¤Ë€±€ÕŸ€±€±€Œa€˜–€€,€g€I>7777 BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@T0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ý¶Û`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡,kŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUPUUUU@UUUUUUð `= I>$ŸUsj$Ÿ0Ô= €,€Éj€ÉjY$øäˀ€,€½5€áÔYô$áÔ€ÕŸ€çïáÔ€Éj€±€½5€Œa€g€s÷€a¨¤Ë€áÔYô$ ޽5€ÕŸYô$ ŽÃô$ÕŸ€±€½5€Œa€€,€0Ô$Ÿ$Ÿss‚7 €$Ÿ€,€ÕŸ€±€˜–€±€Éj€Éj€Éj€áÔ€½5€¤Ë€€,€Œa€a¨I> 5 5 5±²~±²| 5g€¤Ë€ÕŸ€ÕŸ€Œa€€,€€,€g€€,€˜–€˜–€¤Ë€çïÉj€€,€0Ô+Ä~7 €…€…ú—€…sƒ+Ä|UsÉjYáÔ€Œa€½5€Œa€€,€±€Œa€±€±€€,€g€Œa€a¨g€I> 5j= j= ¤Ë€çïáÔÃ7777 BUFR&bÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊBUUUU]kZÖµ­kZÖµ­ï{Þ÷½ï{Þ÷½ï{Þ÷¾sœç9Îsœç9Îsœç9Î÷½ï{Þ÷½ï{Þ÷½ï{ß{Þ÷½ï{Þ÷½ï{Þ÷½àŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð a ŽÕŸ€˜–€€,€¤Ë€¤Ë€¤Ë€s÷€˜–€g€s÷€¤Ë€Éj€s÷€= j 5I>$Ÿ= a¨$Ÿa¨€,€= Us0Ô0Ôjg€Œa€ÕŸ€¤Ë€Us€,€s÷€áÔtPbI—$øçï±€˜–€Œa€½5€a¨j0Ô$Ÿ= a¨€,€= ±²~7 ‚±²|j0Ô= = €,€ô$Y½5€˜–€˜–€€,€áÔ ŽUs$Ÿj0Ôa¨0Ô$Ÿ 5jI>ÕŸô} ç¥$‚²½ŽtPÃI—1-Ã=bçïÉj€Éj€Œa€Œa€s÷€s÷€a¨s÷€áÔ€¤Ë€˜–€ô$˜ï‚1†²ÕøÕø˜ïn6$ø1-ŒºÉÀ…I—UÌUÌ$ø$ø$øUÌtP€7777BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€0I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹Êt­®ˆd)Ž„©l|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUEUUUUQUUUU@UUUUUUQEUUUUð atPb€…€…îbâ-‚Ið¤Ë€ 5+Ä| 5I>±€ÕŸ€çï±€g€¤Ë€¤Ë€˜– Žçï½5€ô$çïÕŸ€Œa€Œa€0Ô+Ä|ú—s‚±²|0Ôs÷€s÷€UsUs0Ô$Ÿ$Ÿ$Ÿ$Ÿ= I>0ÔUsg€I>= 5±²}ú—ú—ssƒ+Ä| 5j0ÔUsI>s÷€€,€çïçï±€Œa€€,€I>€,€a¨= I>= 0Ô 57 ss€Œa€…s€…‚7 ‚±²~±²~7 ‚7 ‚7 ú—ƒ+Ä+Ä| 5= a¨s÷€s÷€= ±²|±²|jUss÷€g€€,€€,€€,€a¨a¨UsI>Usa¨0ÔI>Usg€j+Ä}ú—ƒ+Ä+Ä|7777†BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ!¦:¥±Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð b7 ‚7 €= g€Œa€€,€g€€,€a¨= I>I>a¨g€Œa€çïÃçï±€= 0Ô 5jI>s÷€¤Ë€ÕŸ€Éj€±€¤Ë€€,€Œa€€,€Œa€s÷€±€€,€Œa€Œa€½5€ÕŸ€€,€0Ôj±€±€$Ÿ0Ôa¨˜–€Œa€€,€¤Ë€Éj€Éj€¤Ë€±€±€¤Ë€˜–€€,€g€Us= j±²}ú—ƒ+Ä}ú—‚±²|= g€½5€Éj€áÔ€Œa€±€Éj€ÕŸ€áÔ€áÔY$øô$ô$Y¤Ë€Us±€çïô$±€€,€s÷€a¨Uss÷€Œa€€,€€,€±€ÕŸ€½5€ÕŸ€ô$ ŽáÔ€Œa€€,€¤Ë€½5€ÕŸ€çïçï¤Ë€Éj€a¨0ÔUs€,€s÷€a¨a¨0Ô0Ô7777†BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€00’I$’I$’I)$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUTUUUUUUUUUUð `Us$Ÿ0Ô0Ô= I>UsŒa€½5€ÕŸÃ Ž˜–€¤Ë€Usg€½5€Œa€½5€Éj€ÕŸ€½5€Œa€˜–€¤Ë€½5€ÕŸ€áÔ=bb ŽáÔÀ…¥$tP€ô$Éj€Us= 0Ôs÷€½5$ø1-=bÕŸ€Éj€ÕŸ€ÕŸ€çïçï±€½5€˜–€˜–€s÷€a¨= 5jj$Ÿ= s÷€˜–€˜–€€,€g€s÷€s÷€g€s÷€s÷€½5€Éj€Œa€˜–€Œa€±€½5€€,€$Ÿ$Ÿ±²|UsÉj€±€˜–€g€Usg€Œa€¤Ë€ÕŸ€€,€½5€Œa€Éj€áÔÃ=bn6=b1-$ø½5€Œa€¤Ë€áÔ€ô$ÕŸ€±€Éj€ô$áÔ€±€±€½5€Éj€Éj€½5€áÔ€ô$$ø7777†BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€D0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RÚçÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðU@UUUU@@TUUUUUUUUUUPUUUUUUð aà Ža¨ 5$Ÿ7 ú—‚±²|0Ô= = I>= $Ÿ 5jj0Ô 5 5±²}ú—ú—‚7 s€Œa€O€O€Œas€…‚7 ƒ+Ä+Ä+Ä| 5+Ä+Ä~±²+Ä| 50Ôa¨Œa€a¨ 5+Ä+Ä~7 ‚±²|$ŸUs˜–€Éj€½5€˜–€±€¤Ë€Uss÷€s÷€Œa€±€Éj€g€Œa€Éj€€,€Œa€a¨Us0Ô0Ô0Ôa¨Us˜–€˜–€€,€s÷€Œa€a¨g€g€g€g€s÷€g€UsUsI>= +Ä}ú—€…‚7 ƒ+Ä|j= a¨a¨UsI>= I>UsUsg€a¨a¨Uss÷€˜–€Éj€ô$çïçïô$ô$áÔ€áÔY7777†BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€\0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUUUUUUUUUUQUUU@UUUUUUUUð `áÔUÌ Žg€a¨a¨€,€I>g€½5€ô$˜–€±€s÷€UsUsj+Ä+Ä}ú—‚7 ú—€jI>s÷€g€g€a¨I>I>I>a¨€,€˜–€a¨I>Œa€…b˜ïâ-¥$€áÔ Ž€,€˜–€¤Ë€g€Œa€€,€áÔ€çï±€˜–€Œa€Éj€˜–€€,€€,€Œa€˜–€Éj€s÷€˜–€g€= = 5 50Ô0Ô$Ÿ±²| 5j 50Ô$Ÿ0Ôj$Ÿ$Ÿ= UsUs0Ô$Ÿ+Ä~7 ‚±²~7 ‚±²|$Ÿj= a¨Usa¨s÷€g€s÷€Œa€Œa€Éj€½5€˜–€Œa€áÔbUÌ=b Žçï½5€€,€Uss÷€½5€Éj$øY˜–€½5€½5€½5€ÕŸ€7777†BUFR&bÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê‚UUUUUUUUUUUUUUUUU]ï{Þ÷½óœç9Îsœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{Þ€B„!B„!B„!„!B„!B„!BÆ0ŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%K„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@UUUUEUUUUUEUUUTUUUUUUUUUUUð `ô$çï¤Ë€s÷€½5€±€±€½5€Us±²+Ä}€…‚7 ú—‚±²|j$Ÿ0Ô= $Ÿ0Ô$ŸUs= = Us= I>g€Œa€€,€g€gƒ+Ä|= 0Ô˜–€Œa€±YçïUs= 5j 5 50Ô$Ÿ 5$Ÿjj 5 5€…€$Ÿ$ŸjI>€,€Œa€UsI>0ÔI>j 5j 50Ô+Ä}ú—‚7 ‚±²~7 ‚7 €jUs$Ÿ$Ÿg€Œa€g€¤Ë€€,€0Ôj 5€,€0Ô= = s÷€a¨a¨0Ôj0Ôj 5$Ÿa¨¤Ë€˜–Ø–€g€UsI>a¨Œa€ÕŸI—tPtPâ-‚ çUÌbÕŸ€7777BUFRöbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ@DDEUUUUUUUUUUUVfffffffffffgwwwwwwwwwwwxˆˆˆˆˆˆˆ€Š2ÇBT¶5Ï„e:V×D2ÇBT¶6t­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)އÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUAUUUUUUUUUUUUUUUUUUUUUUUUUð `¤ËÃn6n6Ãô$½5€Éj€¤Ë€ô$½5€Éj ޽5€˜–€˜–€˜–€s÷€g€0Ôs‚±²| 5= I>˜–€±€Œa€s÷€s÷€a¨¤Ë€€,€I>½5‚1†I—=b ŽÉj€Œa€a¨I>€,€˜–€g€±€¤Ë€Œa€Usg€€,€s÷€€,€s÷€˜–€€,€áÔ ŽÕŸ€a¨$Ÿjjj 5 5j+Ä|jjjj= UsI>g€UsI>gÂbbUÌ1- Ž¤Ë€˜–€s÷€€,€¤Ë€¤Ë€±€˜–€¤Ë€Œa€Éj€ÕŸ€çï½5€áÔ1-ÕŸ€˜–à çŒa€Usg€Œa€±€áÔ€±€ÕŸU̘ï1-UÌÉj€½5€¤Ë€áÔ€ÕŸ€Éj€7777€UBUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ00 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUUQ@UUUUUUUUUUUUUTð `g€$Ÿ+Ä|+Ä~±²|0Ôg€¤Ë€˜–€˜–€¤Ë€½5€áÔ€ÕŸ€¤Ë€ÕŸ€½5€±€I>€,€= ±²|7 ú—€…€…€ 5s÷€a¨s÷€±€áÔ€ô$ô$½5€ÉjYÕŸ€Éj ŽçïÕŸÃŒa€€,€€,€= $Ÿ= a¨s÷€0Ô$Ÿg€€,€g€s÷€€,€˜–€±€áÔ€Éj€Éj€Éj€Œa€€,€¤Ë€½5€½5€˜–€s÷€$Ÿg€a¨g€Œa€Œa€I>a¨UsI>Usa¨I>±²+Ä~±²~7 ú—ú—‚7 €j±²~7 ‚±²|7 ú—€…ú—‚7 ‚7 €…€…€Œa€Œa€Œa€Œa€Œa€Oss€…‚±²}ú—ú—ú—‚7 sú—€…ú—ƒ+Ä|= 7777Ô€BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀH0 $’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡+c\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUU@UUQUUUUUUUUUUUUUUEPð `UsI>7 ‚7 ‚7 ú—‚7 ú—€…‚7 €7 ú—‚7 ƒ+Ä|±²}ú—ƒ+Ä|±²~7 €a¨˜–€½5€a¨Usjj$Ÿj= g€$Ÿ 5= = I>Us$Ÿ+Ä~7 ú—ú—ú—ƒ+Ä|js÷€UsUs0Ôj$ŸjUs$Ÿ€,‚±²| 5j0ÔI>= 5 5 5$Ÿ±1-n6îb‚²%Q¥$bÃçïÃn6€…UÌ1-I— ŽI—ÃÉj€ÕŸ€áÔ€½5€¤Ë€±€½5€çïçïÉj€±€áÔ€½5€¤Ë€Éj€áÔI—Ø–€€,€±€çïŒa€s÷€0Ô$Ÿ$Ÿ 5+Ä| 5I>I> 5+Ä|j±²+Ä|7777Ô€BUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ\0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶àŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUQUUUUUUUUUUUUUUQUUUUUUUUUUUð c+Ä|+Ä|j7 ú—‚7 ú—€…€…ú—ú—‚7 ‚±²~±²|$Ÿ0Ôj+Ä| 5I>g€áÔ€½5€½5€±€½5€ÕŸ€½5€¤Ë€¤Ë€½5€½5€ô$ÃUÌ=bUÌbY½5€Éj€Éj€½5€Éj ޱ$øô$½5€€,€Us= = = = I>˜–€áÔYÉj€¤Ë€¤Ë€Œa€€,€˜–€ÕŸ€¤Ë€Œa€Œa€Œa€Œa€a¨0Ô 5 5+Ä| 5I>a¨I>0Ôg€˜–€˜–€½5€±€Œa€½5Y$ø1-1-I—Y±€¤Ë€¤Ë€a¨a¨a¨= s÷€áÔÃI—I—b=bn6b1-ô$çïô$áÔ€½5€ô$±€˜–€±€½5€7777Ô€BUFR&bÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÂUUUUUUUUUUUUUU^sœç9Îsœç9Îsœç9Þ÷½ï{Þ÷½ï{Þ÷½ï{ï{Þ÷½ï{Þ÷½ï{Þ÷¼„!B„!B„!„!B„ Š …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ж5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUEUUUUUUUUUUUUUUEUð `˜–€¤Ë€€,€€,€áÔ€±€áÔ€g€a¨g€s÷€ÕŸ ŽÃÃn6UÌ ŽçYŒa€s÷€€,€±€g€Usg€½5€s÷€g€I>˜–€¤Ë€a¨I>I>$Ÿ0ÔI>I>Uss÷€€,=b Ž˜–€¤Ë€Éj€j 5Œa€= Us+Ä|$Ÿ 5+Ä|a¨ ޽5ÃI—tPŒºb$ø ŽáÔ€½5€±€€,€€,€±€ÕŸ€áÔ€±€€,€Œa€Œa€€,€s÷€ÕŸ€ÕŸ€ÕŸ€½5€Éj€¤Ë€±€áÔ€ÕŸ€s÷€s÷€a¨a¨Us˜–€Œa€˜–€ÕŸ€Éj€½5€ô$YÕŸ€çïÕŸI— ŽáÔ€Éj€˜–€g€0Ô0ÔUs= j+Ä|0Ô= UsŒa€¤Ë€7777BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê 0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUDUUUUUUUUUUUUUUUUUDUEð `˜–€¤Ë ŽI—n6Õø˜ï‚ ç 瀅=bçï7 €j+Ä~±²~±²| 5tPŒº€çïçïÃ$øbtPŒº€…€…UÌ Ž=b1-I—=bô$çïa¨s÷€€,€s÷€¤Ë€¤Ë€˜–€Œa€Œa€Œa€±€˜–€Œa€±€ÕŸYçïÕŸ1-ô$áÔ€½5€½5€¤Ë€€,€= 0ÔUs¤Ë€˜–€€,€¤Ë€˜–€Œa€Œa€s÷€$Ÿ0Ô= I> 5 5 5jI>$Ÿ±²}ú—ƒ+Ä~7 €…€…€…ú—€…€…€…ú—€…ú—€…ú—ú—‚7 ‚7 ƒ+Ä| 50Ô 5±²|±²~±²+Ä|I>€,€a¨0Ô= j+Ä|+Ä|j 57777ŸBUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê 0’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹:V×D2ÇBT¶6”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUE@UUUUPUUUUUUUUUUUUUUUUUUUð `+Ä+Ä| 5±²+Ä|I>s÷€€,€I>= j 5 5+Ä|j±²~7 €…‚7 ú—€…ú—€g€˜–€g€€,€½5€±€g€g€g€Œa€g€I>UsI>Us0Ôj+Ä~±²| 5I>Œa€Éj€ô$ô$ô$áÔà ŽYYô$çïáÔ ŽÃ Žô$¤Ë€Œa€s÷€a¨€,€g€±€çïô$ÕŸ€ÕŸÃ$ø$ø=bÃ$øçïY½5€Éj€ô$çïáÔ€Éj€±€€,€¤Ë€¤Ë€˜–€±€±€áÔ€½5€çïÉj€Éj€½5€±€¤Ë€±€¤Ë€¤Ë€€,€±€Éj€ÕŸ€½5€½5€Éj€±€s÷€Us= $Ÿ7777ŸBUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê80$’I$’I$’JI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUTUUUUUUUUUUUUUð `$ŸI>0Ôj 5$Ÿ= 0Ôjj$Ÿj= I>ÉjÃUÌbUÌ$øYÉj€½5€±€±Yb1-bô$¤Ë€½5€½5€áÔ€çï ŽY$øô}%Q1† çîbtPbtPb1-$øtPîbn61-Éj€áÔ$øYÃÃÉj=bÉÂ1†áÔ€0ÔŒa€+Ä~±²~±²|jUsg€UsI>g€g€€,€s÷€a¨s÷€s÷€¤Ë€˜–€¤Ë€½5€˜–€Us= = $Ÿj 5Us¤Ë€s÷€½5€½5€Œa€€,€g€I>I>I>g€Œa€¤Ë€Œa€¤Ë€±€˜–€Usg€= I>0Ô+Ä|j$Ÿa¨€,€€,€g€s÷€Œa€¤Ë€€,€g€7777ŸBUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊL0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’Km¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡,kŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUTU@UQUUUUUUUUUUUUð `Usa¨a¨s÷€g€¤Ë€Œa€Œa€a¨€,€˜–€¤Ë€€,€a¨UsI>s÷€= I>a¨Us¤Ë€Œa€s÷€Œa€Œa€çï½5€ÕŸY ŽÃYáÔ€½5€±€˜–€Œa€€,€€,€¤Ë€g€j±²~±²|I>$Ÿ±²+Ä|$Ÿ 50Ô$øṲˀ$Ÿ+Ä}ú—‚7 ss‚±²|$ŸI>I>I>= 5+Ä| 5 5$Ÿ0Ôj= s÷€0Ô 5+Ä~7 ‚±²+Ä~±²~7 ƒ+Ä|= ½5 Ž=bY˜–€¤Ë€áÔ ŽáÔ€Éj€çï1-Éj€ô$ÕŸ€€,€I>a¨Us$Ÿ= €,€˜–€Œa€Éj€Œa€s÷€€,€˜–€±€±€ô$áÔY1-UÌ$øÃô$½5€7777ŸBUFRæbÿ« fÊ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Êd0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUTUUUUUPEUUUUUð `Œa€0Ô= I>s÷€±€±€±€½5€¤Ë€Œa€½5€áÔ€±€áÔ€ô$Yçïn6îb½ŽtPtPI— ŽáÔ€Éj€˜–€Éj€½5€ç€½5€Éj€Œa€Œa€˜–€€,€s÷€˜–€˜–€±€Éj€ô$=bô$ÕŸ€˜–€Usg€ 5+Ä|0ÔI>I>$Ÿ$ŸI>= $Ÿj0Ô0Ô= 5s÷€a¨a¨Us= $Ÿ+Ä~±²~7 ‚7 ‚7 ‚±²~±²~±²}ú—ú—‚7 ‚±²~7 ú—ú—ú—ú—‚7 ‚±²| 5j±²+Ä~±²~7 ‚7 ‚±²~±²|$Ÿ 5 5±²| 5 5j0Ôg€˜–€½5€ÉjYbb=bYÕŸÃYô$Éj€áÔYb7777ŸBUFR&bÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï{ß{Þ÷½ï{Þ÷½ï{Þ÷€„!B„!B„!D!B„!B„!B†1ŒcÆ1ŒcÆ0Š„©lkŸÊt­®ˆd)Ž„±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUAUUUð aîb½ŽtP€áÔ€±€Éj€áÔ€ÕŸ=báÔUÌÃUÌô$Œa€Œa€Œa€±€¤Ë€¤Ë€s÷€ÕŸ€áÔ€Éj€Éj€Œa€a¨s÷€¤Ë€¤ËÃô$áÔ€ô$ÕŸ€ÕŸ€¤Ë€0Ô 5j+Ä+Ä|I>½51-b1-Ãô$ô$ô$ Ž=bn6UÌô$ÕŸYÕŸ€áÔ€ÕŸ€Œa€= €,€a¨a¨±€çïÕŸ Ž Ž ŽY$ø$øçïçï$øUÌ=bÉ ç çô}½Ž±YtPUÌI—Ã$øYI—tP‚=»UÌçïÃ$øáÔY$ø1-1-$ø$øY½5€¤Ë€s÷€s÷€Us±²~±²|0Ôj 5$Ÿ$Ÿjj$Ÿg€s÷€7777BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÛmÛ`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±¯„e:V×D2ÇBT¶5Ï„e:V×D2ÇBVƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUýà`g€[€[€I>Us= 5 5 5 5$Ÿs÷€½5€Éj€Éj€½5€½5€½5€Œa€s÷€¤Ë€ÕŸÃ=bÃUÌtPh=b$øçïçïÕŸ€¤Ë€¤Ë€˜–€ÕŸ€ô$Yô$ÕŸ€½5€˜–€s÷€˜–€±€±€çïÃ$øYô$ÕŸ€Éj€½5€±€±€¤Ë€˜–€ÛºÕŸ€çïÛº€,€€,€€,€Œa€Œa€¤Ë€çïçïYô$±€¤Ë€Œa€Œa€g€$Ÿ~¥}|= Ûºô$˜–€€,€g€s÷€Us[€€,€Œa€çï=bÃ Ž ŽÛºÉj€±€g€€,€€,€¤Ë€€,€g€½5€±€˜–€Œa€[€g€g€[€s÷€Œa€¤Ë€˜–€Œa€±€¤Ë€s÷€ 5¥}~¥}}îb€ú>€7777÷€BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@(0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUUUUUUUUUUUUUUUUUUPUUð aú—€ 5a¨UsI>UsUsa¨g€s÷€a¨ Ž˜–€a¨€,€s÷€áÔ€±€g€s÷€Usj+Ä~±²~7 ú—‚7 €+Ä| 5+Ä| 5 5= s÷€ŒaY=b Ž$øçïs÷€$Ÿ$Ÿ$Ÿjj= €,€˜–€¤Ë€Éj€Œa€½5€±€¤Ë€±€½5€Éj€±YI—YÕŸ€áÔ€€,€s÷€0Ô= I>0Ô˜–€çïô$ÕŸ€½5€¤Ë€ÉjYáÔ€ÕŸ€Éj€g€çïô$¤Ë€˜–€±€˜–€¤Ë€Œa€g€$Ÿ 5= €,€±€€,€±€g€€,€ÕŸ€±€ÕŸ€Éj€€,€I>$Ÿ 5j7 €…€…€…€$Ÿ˜–$ø€…€…n6tPI—1-7777÷€BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@<0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈSKc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUýàa1-Ã$ø1-=bI—$ø$øÛº±€g€~¥}|j˜–€çïYÛº¤Ë€˜–€˜–€˜–€¤Ë€½5€ÕŸ€ÕŸ€ÉjÃÃÛºÉj€€,€g€g€€,€[€g€Œa€Éj€ÕŸ€Éj€Éj€¤Ë€Éj€½5€¤Ë€çïÛºçïô$ô$Ûº1-1-$øô$ÛºÕŸ€çïÉj€€,€Œa€˜–€Éj€ÕŸ€s÷€s÷€Us= [€Œa€¤Ë€±€½5€çïUÌ€…bI—=bYŒa€±€[€I>Us½5€ô$ô$YYô$Ûºô$Ûºô$Éj€Éj€ÕŸ€çïçïÃ$øÃô$˜–€€,€¤Ë€±€±€¤Ë€½5€Éj€±€ÕŸ€¤Ë€Œa€½5€ÕŸ€ô$Éj€ÛºÕŸ€¤Ë€±€0Ô7777÷€BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê@P0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUU@UUUUUUUð b±²~7 ú—ú—ú—€ 5$ŸUs˜–€¤Ë€€,€I> 50Ô0Ôj= g€g€±€Éj€Œa€g€$Ÿ€…ú—‚7 €…€…‚7 €= áÔ€˜–€Œa€˜–€= 0Ôjjj0Ôs÷€s÷€±€½5€s÷€g€Us7 s€…€Œa€Œa€…€= g€¤Ë€˜–€= 0Ô0Ôjj0ÔUs€,€g€s÷€Us= 0Ô= j+Ä~±²}ú—€…ú—€ 5$ŸUsg€s÷€Us= $Ÿj$Ÿ$Ÿ$Ÿ$Ÿ$Ÿ$Ÿ$Ÿ 57 ú—‚7 €Œa€O€Œa€Œa‚7 ‚7 ‚7 ƒ+Ä| 5$Ÿ 5 5 5j$ŸI>0Ôjú—sú—€…s‚±²|I>˜–€7777÷€BUFRöbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊBUUUU\ç9Îsœç9ÎsœëZÖµ­kZÖµ­kZÖµ­o{Þ÷½ï{Þ÷½ï{Þ÷¾sœç9Îsœç9Îsœç9Î÷½ï{Þ÷½ï{Þ÷½ï{Њt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%KcŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýà]1-“. 'À~ð F0Às÷YIð&\ ë™pýà9ûÀdµ@¤ËÃa¨c  @ øPð @@±b²dÆŒ0 ReÀ±’ÕŸ¼KT Yø &% X€@¤ËY1†Ÿ¼|(Œ0 LK@ô$zÄ28KT –¨Ð9ûÀ9ûÀ±èHdÝÐÈŒ0ýà$Ÿja¨ÃP¡ LK@½5bÏÞ«˜Æ&% ReÀ±I—Ĉ –¨ &% ReÀ±bôÖé¬ ™p)2àdµ@ÕŸ·tÄÄ´ÆÐ,@ dµ@½5«?nèÝÐ Yø¦°,@ dµ@½5b²IðIð“àã`3á@˜–I—1†&\ ÓX¦°,@ mÝÛº7777|BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUýàaY ŽYçï½5€˜–€½5€Œa€s÷€s÷€s÷€[€$Ÿj[€$Ÿ0Ô[€Usg€€,€Œa€Éj€±€±€ÕŸ€ÛºÉj€¤Ë€[€Usj~¥}~¥}~¥}|Us½5Y$øô$ ŽçïÛº½5€ÛºÉj€ô$Ûº$ø$øçïÕŸ€ÕŸ€ô$½5€˜–€¤Ë€Éj€½5€ÕŸ€çï Ž=bYÕŸ€Éj€±€ÉjY=bhb=b$øô$s÷€0ÔUs= 0Ô0ÔŒa€Éj€ô$UÌ$øÃô$ÛºÕŸ€çï ŽY1-bI—I—b1-$ø Žçïô$ÕŸ€ÕŸ€½5€ÕŸ€ÛºYçï½5€Éj€¤Ë€˜–€˜–€¤Ë€ô$ÃUÌbbbbÃÕŸ€€,€7777@ BUFRÆbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$–Ûm¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ж5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@,@ `[€*¹€6î€[€€,€˜–€·ÃPçïÏ…·Œa€ªæÛºçïÃC|+[æO±+7GÃçïô$ÛºÃP·ۺυۺçïÛºY$øçïO±Ãçï ŽYÛºÛºYÃ$øÃP€,€€,€OX€C#€OX€g€s÷€€,€ž±YÞ±6î€j„€jŒa€Œa€ž±·Ï…ªæž±Ï…ÃP·ž±g€€,tP‚+k‚·ÍÐ7·Ûºs÷€ž±ÃPÃP7G·t·t¥$7G7GÃ[æ7G€çïۺυ·ÃPô$Ã[ætP˜ïO±€ÃPh€…+€ô$Y7G+÷Ï…ÛºÛºÛºçïY+C|+C|+€7777UÌBUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€00’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð aI—tPtPn6tPb½Ž¥$¥$€…tPbÃY$øYô$Œa€s÷€ô$ô$UÌYçï¤Ë€½5€½5€¤Ë€çïb±YÉÃŒºÕøtP$øô$ÃÃô$çïáÔ€ô$YáÔ€½5€½5€Éj€áÔ ŽI—1-1-=bUÌUÌUÌÃI—1-ô$ÕŸ€çïáÔ€ÕŸ€áÔ€ÉjY$ø²nnIðÖQ‚V%Iðîb˜ï=b=bÃÕŸ€½5€¤Ë€€,€¤Ë€jjj0Ô0Ô$Ÿ 5$Ÿ$Ÿ$Ÿj$Ÿ0Ô= 0Ô0Ô= = jj+Ä~7 ‚±²~±²~7 € 5˜–€±€Éj€±€g€= Us$ŸUsUs€,€Éj€½5€Éj€7777@ BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€D0’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹:V×D2ÇB–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUPUUUUUUUUUUUUUUUUUUUUUUPUUUUPýà`±€¤Ë€€,€€,€= j~+k‚¥}|I>Œa€g€[€[€g€g€s÷€[€˜–€Ûºç€ÕŸ€ô$Yô$çïÛºÛº¤Ë€Œa€s÷€s÷€˜–€€,€g€g€[€Œa€¤Ë€±€±€ô$ÃYçïçïÛºÛº±€Œa€[€s÷€[€Us€,€s÷€˜–€ÕŸ€˜–€Œa€˜–€½5€ÛºçïçïÛºçïô$Yô$çïô$ô$YY½5€˜–€€,€I>[€˜–€¤Ë€˜–€˜–€s÷€s÷€s÷€s÷€˜–€±€ÕŸ€ÕŸ€½5€½5€Œa€g€= $Ÿ0Ô$Ÿ~¥}|$Ÿ= g€s÷€s÷€˜–€[€g€g€±€¤Ë€Éj€˜–€€,€±€[€= j~+k€7777@ BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê€\0$’I$’I$’II$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ˜×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUU@UUUU@UUUUUUUUUUUUUUð c+Ä~±²|$Ÿ$Ÿ 5 5 5jjj$Ÿ= ÉjI—=bô$ô$çïÉj€Éj€I>0Ô+Ä|$ŸŒa€ô$$ø ŽÕŸ€±€˜–€¤Ë ŽYb˜ïI—UÌ ŽY½5€s÷€0Ô+Ä~±²}ú—‚7 €0ÔÉj€áÔ=b=bYáÔ€½5€Éj€ô$bn6I—1-ô$ÕŸ€çïÉj€s÷€= +Ä~±²+Ä|I>g€՟ Žô$çïÕŸ€Éj€Éj€ÉjY=b€…UÌUÌ$ø$ø$øô$áÔ€¤Ë€a¨˜–€€,€¤Ë€ô$Y1-$øYô$Éj€ÕŸ€Éj€çïUÌtPb=b1-$øYçïÕŸ€Éj€Œa€Œa€g€¤Ë€ÕŸ€ô$à ŽáÔ€˜–€˜–€7777@ BUFR&bÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê‚UUUUUUUUUUU]ï{Þ÷½ï|ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷¾÷½ï{Þ÷½ï{Þ÷½ï{À!B„!B„!BŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUTUUU@UUUTUUUUUUUUUUð `€,€˜–€áÔ=bbtP˜ïUÌI—ÃYYÕŸ€I>0Ô= Us˜–€¤Ë€¤Ë€g€a¨çïbUÌçïbn6$ø=bÃÃÕŸ€s÷€½5€= j 5 5€…ƒ+Ä|ja¨0Ô= €,€ 5I>s÷ñ€Éj=b±€Œa€a¨0Ô±²~±²}€…€…ú—€…€…ú—€Œa€Éj€±€¤Ë€Œa€˜–€Œa€¤Ë€½5€çïY½5€˜–€½5€˜–€I>= ú—€…€Œas‚±²| 5UsçïYô$UsI>g€g€Éj1-b=bb±Y±Y¥$n6YçïÕŸ€ÕŸ€½5€Éj€ô$bŒº$øáÔ$øUÌ$øY1-ô$Éj€˜–€€,€˜–€Œa€7777BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `I>= = 0Ô= j$Ÿ= I>I>Usa¨s÷€€,€˜–€˜–€±€¤Ë€±€Éj€ÕŸ€áÔ€ÕŸ€½5€Œa€Œa€€,€ 5s‚7 €0Ô+Ä|s÷€±1-˜–€½5€±€ô$Ãô$bI—1-à ŽYY½5€€,€s÷€s÷€¤Ë€½5€¤Ë€Éj€ÕŸ€¤Ë€½5€¤Ë€±€Éj€ô$çïYà Ž1-YÃ$øYçïçï1-ô$˜–€a¨= 0Ôa¨˜–€€,€Éj€€,€Œa€˜–€±€Éj€±€½5€áÔ€çïáÔ€áÔ€çïÉjYYáÔ€áÔ€áÔ€½5€˜–€s÷€€,€a¨g€s÷€s÷€UsŒa€±€½5€±€±€±€Éj€Éj€ÕŸ€áÔ€ÕŸ€Éj€±€±€˜–€Œa€7777Ÿ€BUFR¶bÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ 0 $’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*kŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ ]Y“.d?x q°ã`9ûÀ˜–bÄé¬  /M`ReÀ±1-ÏÞŸ¼?x ë @€[€’|Ÿ >¸Ø~ðýà@@€,I—“.ˆ –¨-P,@ X€@ŒaYbZd|( 'Àð F0ÀÏ…²oš )$˨+|ÐOX€ÀBÀô$ÏÞ1†ˆ L¸Ðýà9ûÀI>a¨ÃPa¨ÃP†  'À'¬@s÷€çï²c ÓXw@= mÝÉj1-ôÖÄ´ L¸™p)2àReÀ¤ËI—“.&\ ‰h™p)2àReÀ±Ã²c ‰h™p)2àg€çï’ÕŸ¼?x øPÐð O€0Ôj$øzĸء 5= ’|’|ÃP“à q° 'À„€0Ô7777€±BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ40I$’I$’I$”’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„­sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUDUUUTUUUUUUUUUUUUUUUUUUUUUUð `I>= 0Ô= $Ÿ+Ä|+Ä~7 ‚7 €…ú—sú—ƒ+Ä|a¨˜–€˜–€¤Ë€±€˜–€¤Ë€€,€€,€Œa€½5€Œa€s÷€a¨$Ÿ±²~±²~7 ‚7 ‚7 ƒ+Ä|= g€˜–Y½5€s÷€€,€a¨Œa€½5€ô$ Ž=bÃáÔ€½5€±€±€Œa€˜–€s÷€= I>= Éj1-=b=b1- Ž Ž ŽÃ$øI—UÌ$ø=bYYçï¤Ë€±€±€s÷€€,€Us¤Ë€áÔY=b1-$ø=bçïáÔ€çïÃUÌUÌI—Ã$ø$ø½5€˜–€s÷€g€0Ô$Ÿ0ÔI>½5Y$øb1-I—UÌÃÕŸ€ÕŸ€çïô$ô$áÔ€áÔY Žçï½5€7777Ÿ€BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀL0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$–Ûm¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUTUUUUUUUUUUUUUUUUUUUUUUUUð `Usj±²~±²|$ŸUs˜–€¤Ë€Éj€±€½5€±€±€Éj€±€¤Ë€˜–€Œa€˜–€˜–€$Ÿ±²~±²~7 ú—€…€…‚7 ‚±²~±²|$ŸI>= a¨±€áÔ Žô$YÃà ŽÃ1-1-YáÔ€ÕŸ€ÕŸ€çïÉjYÃ$ø$øY$ø=b1-1-$ø=b1-Yô$áÔ€çï±€Éj€Éj€ô$ÕŸ€½5€½5€¤Ë€ÕŸ€áÔ€çï½5€áÔ€ô$Yô$ Žô$ÃÃçï¤Ë€ÕŸ€áÔ€ÕŸ€Éj€¤Ë€Œa€a¨= a¨s÷€¤Ë€ÕŸ Ž ŽY ŽÃ Ž Žô$ Ž ŽçïÉj€Éj€€,€I>I>I>$ŸUs±€ô$ Ž=bbtP€7777Ÿ€BUFRæbÿ« fÊ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÀ`0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUU@UUUUUUUUUUUUUUU a$ø1-$ø$ø1-ÃÃÃ1-$øÃY1-[æ1-Yô$ۺۺυυ$øY ŽÃÃ$ø1-Ã1-1-ô$±€Œa€OX€I>OX€I>Œa€OX€jI>€,€¤Ë€±€Ï…½5€Éj€Ï…çïÏ…çïYۺυ½5€¤Ë€€,€g€OX€= = 0Ô0ÔZ}h‚™H| 5I>s÷€Œa€Œa€±€˜–€˜–€±€±€±€¤Ë€¤Ë€¤Ë€Œa€€,€g€OX€¤Ë€½5€Éj€±€±€Ûºçïçï1-U̘ïUÌÃI—€…tPtP¥$€…ô}t©‚€Þô}t©½Ž€…UÌÉj€±€½5€çïI—èHŒºI—çïÛºô$ô$ô$ô$7777Ÿ€BUFR&bÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊÂUUUUUUUUUUUUUUUUUUUUUUUUU^sœï{Þ÷½ï{Þ÷½ï{Þ÷½B„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œc!@‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUPýà`ô$YYô$çïYY ŽY Žô$çïçïÛºÕŸ€Éj€ÕŸ€ÕŸ€ÛºÛºÛºÉj€ÛºÕŸ€çïçïô$ÕŸ€Éj€½5€½5€Œa€€,€€,€[€€,€Œa€çïYYô$à Ž$øÃÃ$øI—Ã1-1-UÌ1-=b$ø ŽY$øUÌ$øçïÛº±€½5€ÕŸY1-=bUÌbhUÌ1- Žô$ÛºÕŸ€½5€¤Ë€[€j$ŸI>0ÔI>g€Usg€˜–€½5€±€½5€ÛºYÛº½5€˜–€çïÕŸ€¤Ë€±€±€€,€j~¥}~¥}|$Ÿj 5I>˜–€¤Ë ŽÉj€¤Ë€g€= ~+k‚+k‚+k‚¥}~+k€7777BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê0$’I$’I$’II$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUTUUUUU@UUUUUUUUUUUUUð b7 €jÕŸ1-I—I—1-ô$Yô$½5€Éj€ô$Éj ŽÕŸ€€,€g€$Ÿ0Ô 5+Ä~±²+Ä|= ŒaY$ø=b1-1-ÕŸ€ô$1-=bÃô$ô$áÔ€±€a¨0Ô±²~7 ‚7 €…€0Ô= gÂI— ŽÃáÔ€ô$½5€Éj$øÃ Žô$áÔ€ô$ô$¤Ë€€,€= 7 ssú—€ 5Us˜–€±€±€çï1- Ž Žn6±Y€…UÌ1-I—I—ô$˜–€€,€±€˜–€g€€,€s÷€áÔ Ž$ø=btP¥$$øÃ=btP±Y˜ï€…I—UÌn6$ø ŽÉj€a¨€,€Œa€= = I>a¨Œa€¤Ë€˜–€Œa€Œa€7777|BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê(0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@UUUTUUUUPUUUUUUUUUZUUUUUUð `s÷€˜–€a¨g€g€= $Ÿj7 ‚7 ú—ú—sss€…€…ú—‚±²|$ŸUs€,€g€a¨Usg€a¨UsI>= $Ÿj7 ‚7 ú—ú—‚±²|j= ˜–€ô$Éj€½5€½5€Éj€½5€¤Ë€½5€ÕŸ€ÕŸ ŽÉj€€,€Us$Ÿ+Ä~7 ƒ+Ä~7 ‚7 ‚±²|j±1-n6tP˜ïÉÃ½Ž€…UÌÃÃô$±€½5€Œa€€,€Éj€áÔ€ÕŸ€çïYYÃ$øUÌUÌ€…ÉñY˜ï½ŽÉýŽîb‚%Q¥}ƒ € Äô}îbîbÉÃŒº1-Ã1-UÌUÌ¥$tP€…n6Œºb€…btP1-Yô$YáÔ€7777|BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ê<0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `¤Ë€¤Ë€˜–€½5€¤Ë€¤Ë€s÷€ÉjÃUÌtPbUÌUÌI—UÌbtPŒº±YÉÃŒºI—I—Ã Ž Ž$ø ŽçïÕŸ€áÔ€áÔ€ÕŸ€½5€Éj€Éj€½5€½5€½5€Éj€±€½5€½5€€,€Œa€s÷€UsI>= ±²+Ä~±²|s÷€s÷€˜–€½5€áÔ€˜–€˜–€±€Éj Ž1-UÌÃà Žô$ô$±€s÷€I>= 0Ô$Ÿ0Ô±€ÕŸÃ=bUÌI—$ø ŽUÌn6€…Œºbn6tPUÌb1-Ã$øÃçïÕŸ€¤ËYI—˜ïbUÌ1-=b$ø=bn6tP±YtPŒºtPn6€…n6=b=b1-ÃáÔ€¤Ë€7777|BUFRÆbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÊT0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠc¡*[øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ `çïÃI—UÌ[æh±Y½Ž€…Œº±YŒº[æ=bI—=b1-$ø1-Ã$ø$ø$ø1-U̱Y½ŽÉÃ¥$±Y±Y½ŽÜ\?‚€ÞƒuV~h̓V~€Þ‚1†1†ht‚1†²ÉñYŒº˜ïÉÃô}Ið=»ÜÕøŒºUÌ=bUÌI—[æUÌ1-hI—=b$ø$øÃI—à Ž1-1-Ã$ø Ž ŽÃ=b[æ$øÃ Ž Ž Žô$ô$çïÏ…½5€˜–€OX€= I>s÷€g€[€[€g€[€I>= j$Ÿ0Ô0Ô0ÔI>g€€,€±€Œa€Œa€= 5$ŸjjI>I>= s÷€s÷€7777€…BUFRæbÿ« fÊ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Êh0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUUUDUUUUUUUUUUUUð `Œa€g€ 5jj 5±²~7 ‚7 ú—‚7 ‚7 ú—ú—‚±²| 5s÷€Éj€Éj€ÕŸ€Éj€½5€áÔ€ô$çïô$ ŽáÔ€ô$¤Ë€s÷€0Ô$Ÿj$Ÿj 5 5 5I>a¨a¨g€s÷€s÷€g€g€Usa¨= j$Ÿ= jj+Ä|+Ä~±²}ú—€0ÔI>s÷€UsUs€,€s÷€g€¤Ë€±€ç€g€a¨= $Ÿ 5ú—‚7 ú—€Œas€…ú—€ 5a¨€,€g€a¨g€a¨s÷€g€±€½5€˜–€€,€UsUs= ±²~±²}ú—ú—ú—‚7 € 5s÷€±€s÷€˜–€±ÃYáÔ€ô$ô$ô$Éj€UsI>s÷€s÷ÉÀ7777|BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@0I$’I$’I$”’I$’I¶ÛmÉ$’I$’I$–Ûm¶Ûm¶Ûm»m¶Û`Šˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©ljáN•µÀ …1Е-te:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUU@UUUUUUUUUTUUUUUUUUUUUUð `Us[€[€UsI>0ÔjUsg€$Ÿ 5jUs= = g€[€I>= I>= = $Ÿ 5+Ä~7 ‚±²+Ä+Ä|j0Ôs÷€Éj€½5€¤ËYô$Y=b[æh[æhUÌ€…tP=b1-1-Ã$øÃ Ž1-[æ˜ï½Ž‚²[æ=bô$ÃÛºô$çï±€Œa€s÷€[€0Ô+Ä+Ä}ú—€…ú—ú—€ 5Us€,€g€g€s÷€€,€Œa€Éj€ô$1-çïÛºÛºçïÕŸ€ÕŸ€ÛºÛºÉj€= = s÷€Ûº1-1-$øçïçïÕŸ Ž$ø1-=b1-ÃY$ø$øYÛºÉj€¤Ë€±€±€½5€ÛºÛºçï Žçï7777|BUFRöbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@@"""""UUUUUVfffffffffffgwwwwwwwwwwwxˆˆˆˆˆˆˆˆˆˆ€Š¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBZçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUAUUUUUUUUUUUUUUUUUUUUUUUUUUUýà`Ï…½5€¤Ë€¤Ë€±€Ï…çïÏ…ô$Ï…˜–€±€€,€g€OX€I>j~¥}|s÷€I>$Ÿ[€Œa€˜–€g€s÷€±Y ŽçïÛº±€Ûº½5€jjI>I>0Ô= s÷€Ï…ÃçïçïI—=b=b[æhtPŒºh€…hh=bÃô$˜–€s÷€±€±€ô$À…hI—O±=b1-ÃÃO±Ã ŽYçïYçïÉj€OX€= $Ÿjj= ¤Ë€Éj€±€Œa€¤Ë€˜–€€,€±€Œa€±€Ûº¤Ë€s÷€s÷€€,€g€[€j0Ôs÷€g€0Ôg€[€€,€I>I>I>= [€g€s÷€€,€Œa€[€I>0Ô 57777˜BUFRbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÂLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@<0 $’I$’I)$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛm¶Û`‹k€" c¡*\e:V×D2ÇBT¶5ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@àB„!B„!B„!B„!B„B„!B„!B„!B„!B„!B„!B„!B„!B„!B„!`Œa€gÂèHô$ô$zbZŒa€ÛºÃÃY Ž$øçï¤Ë€Œa€Œa€€,€±€±Ãۺυυçï=bhhO±€çïÃPÛºçïۺۺυÃPô$çï$øçïŒa€s÷€gƒ“†ÿ“†üs÷€±Y¥$èH²[æ$ø$ø1-±Y½Ž‚1†ô}èH½Ž¥$Œº[æ ŽÛº±€˜–€¤Ë€¤Ë€ÛºÃ[æÃC|O±½Ž˜ï ޽5€ÃP ŽÛºÏ…YC|C|YÛºs÷€½5€˜–€±€˜–=b Ž1-±YhYçïYçï=bÃO±˜ïŒº=b ŽÃô$$øçïY ޽5€s÷€˜–€±€½5€ÛºÃP±€½5€7777k‚BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@T0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I%¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƺ”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUDUUUU@UUUUUUUUU@UUUUð `= = s÷€I>Usg€I>Us0Ô= $Ÿ0ÔI>+Ä~7 ú—ú—sú—€[€= [€€,€Œa€s÷€Ûº½5€½5Y˜–€½5€çï€,€I>0Ô+Ä|7 ú—€ 5[€ÛºÃçï±€g€Us0ÔI>I>Us€,€s÷€0Ô0Ôj7 ú—ú—‚7 ƒ+Ä|I>±$øI—$øçïô$ÕŸ€ÕŸÃ[怅[æh=bUÌ Žô$¤Ë€0Ô 5js÷€Œa€¤Ë€€,€Éj€Ûº¤Ë€Éj€½5€Éj€½5€ÕŸ€ÛºÉj€½5€0Ôj±²~±²}ú—€…€g€jjjI>€,€½5€çïÛºô$=b$øÃÛºÛº1-$ø Ž$ø7777$BUFR&bÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËBU\ç:Öµ­kZÖµ­kZÖµ­k[Þ÷½ï{Þ÷½ï{Þ÷½ï|ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷¾÷½ï{Þ÷½ï{Þ÷½ï‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS S\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUU@UUUE@UUUUUUUUUUTUUTð a ŽYÛº¤Ë€Œa€€,€Œa€½5€ÛºÕŸ€çïY1-Éj€±€Éj€Ûº1-=b˜–€Éj€çïŒa€˜–€±€±€s÷€j$Ÿ+Ä}€…€O€…€j[€€,€g€g€[€¤Ë€I>[€˜–€½5€½5€¤Ë€Œa€Us$Ÿ+Ä|j 5$Ÿ7 s€O€Œa€jg€˜–€½5€ô$½5€½5€¤Ë€¤Ë€ÕŸ€Éj€±€½5€±€s÷€[€[€s÷€= = = Us[€Œa€ô$1-UÌ[æhI—1-$øUÌŒº˜ï¥$[æ$ø1-Ãô$ÕŸ€Ûº€,€0Ô7 ƒ+Ä|$Ÿs÷€Éj€¤Ë€€,€[€g€s÷€Œa€ÕŸ€s÷€UsUs0Ô+Ä}ú—€Œasƒ+Ä+Ä| 5g€Éj€7777BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUPUUUUUUUUUUUUUUUUDUUð a1-UÌ1-1-1-$ø$øYÃUÌI—1-Ãà Žô$çïÛºŒa€±€€,€€,€Œa€Ûº Ž€…‚ ç±Y€…1-YÛºI—1-=b1-1-ÃÉj€¤Ë€€,€0Ô+Ä}ú—€…€…€ 5Us½5äˀg€¤Ë€Œa€±€ÕŸ€ÕŸÃ=b=b=bÃô$¤Ë€½5€€,€0Ô€,€s÷€Usg€±€ÕŸ€Ûºô$ô$çïÕŸ€ÕŸ€Éj€¤Ë€ÕŸ ŽY ŽY Ž1-1-YÕŸ€s÷€˜–€[€UsUsg€˜–€€,€€,€Œa€Us[€[€€,€Œa€Œa€Œa€¤Ë€˜–€€,€g€ 5+Ä|ss‚±²+Ä|[€ÕŸ€ô$ÕŸ€€,€˜–€= Uss÷€7777,€BUFRöbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€@DDDDUUUUUUUUUUUUffffffffffffwwwwwwwwwwwwˆˆˆˆˆˆˆˆˆˆ€ŠøFS¥mpC!Lt%Kc\ø>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUPUUUTUUUUUUUUUUð `s÷€˜–€½5€±€½5€Éj€s÷€= ±²~±²}ú—s€Œasƒ+Ä|UsÛº=b ŽÛº½5€˜–€Œa€¤Ë€± Ž$ø=b=bI—UÌ[æ=b$øÕŸ€±€±€±€±€˜–€¤Ë€Éj€ô$ô$Éj€˜–€˜–€±€˜–€€,€¤Ë€Œa€¤Ë€0Ô 5 5 57 ú—‚±²~7 ú—€…sú—‚7 €I>[€0Ô 5 5 5= $ŸI>˜–€¤Ë€Œa€s÷€s÷€g€0Ô±²~±²}ú—€…‚7 €[€½5€çïçïçïô$Ãô$ÃÉj€ô$I—hh[æ$øYÛºÉj€jUs0Ôg€0Ô˜–Y Žñ€ÕŸ€½5€ÕŸ€çïYÉj€ô$Éj€˜–€g€7777€sBUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€80$’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUQUUUUUAUUUUUUUUUUTUUUUð `€,€0Ô$Ÿ+Ä|±²+Ä|[€[€ô$ý5€Éj€½5€¤Ë€½5€¤Ë€ÛºÛºÉj€Éj€Œa€s÷€[€[‚7 € 5±²~±²~±²| 5gÂY ŽÕŸ€˜–€˜–€˜–€¤Ë€±€Ûº1-ô$€,€= 5j0Ô 5 57 ‚±²|s÷ Ž=bY¤Ë€€,€s÷€€,€±€ÉjÃŒºtP=bUÌUÌ1-ÃÉj€€,€[€UsI>[€ŒaÃ=bYÉj€s÷€s÷€[€€,€Œa€Œa€˜–€¤Ë€¤Ë€Œa€I>= jú—ú—ú—ú—‚7 € 5[€€,€s÷€[€€,€s÷€Œa€¤Ë€€,€Éj€Ûº±€Éj€g€$Ÿ+Ä}ú—‚7 ‚7 ‚7 ‚±²|j= 7777j€BUFR¶bÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€P0 $’I$’I$’RI$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[èFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]bc L¸Ð$Ÿ@@s÷€ÕŸ‚²28 ‰hX3ðReÀ˜–UÌbZdˆ¸Ø€ 'ÀjI>Yd @Ü™p#`5gàdµ@ÕŸI—1†ˆ –¨ 9ûÀ^šÀ¤Ë€çï²èHIð @€ 5$ŸªæbZ鬯~ð,@ ReÀ€,Y²?xB@ýà9ûÀdµ@€,’ÕÏÞÃP€O€¤Ë‚Iðc ÝÐ L¸Ðð F0À½5ÏÞÄ´ ‰hÐ-pF0À­óA=bèHĈÈÐ)2àjÏÀçïzÄö: ŠÌ¾h'¬@I>’|Œºƒ1ßÅf eÔ¸.ŠZàÀBÁUÌzÄc È \ÀReÁY1†d?x~ð!‘ÀC#€†Gçï7777€ÛBUFR&bÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë‚UUUUUUUUUUUU\cÆ1Œg9Îsœç9Îsœç9ÎsœëZÖµ­kZÖµ­kZÖµ­o{Þ÷½ï{Þ÷½ï{Þö„!B„!B„!B ŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%MsáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUU@UUU@UUUUUUUUUUýà`½5 ŽO±=b[æI—I—ÃÃçï¤Ë€¤Ë€±€Œa€€,€s÷€±€€,€s÷€˜–€½5€¤Ë€Éj€g€s÷€½5I—½Ž±Y€…h[æ1-ô$O±=b½5€[€Œa€Éj€ô$ ŽÃÛºô$çïÛºçï1-ô$±€ÛºÏ…±€€,€= 5+k‚¥}}tP€ú>tPƒ|$Ÿ±€Éj€½5€±€˜–€˜–€€,€g€€,€g€= 5$Ÿ}îbtP€ú>€ú>€€,€ú>€I>±1-€…1-±€s÷€0Ô= jg€υ½5€Œa€€,€s÷€OX€ 5 5îbîbîb‚¥}| 5Œa Ž1-Ï…˜–€g€I>Œa€€, Ž1-€…$ø˜–€±€¤Ë€¤Ë€0Ô0Ô7777BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀ 0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’Ûm¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUTUUUUUUUUUUUUUUUUUð c+Ä|7 ƒ+Ä|€,€ô$1-à ŽÛºçïçïçïI—1-˜ïÉ ç=»1†ÉÃŒºŒºŒºUÌ=b$øI—hUÌI—1-UÌŒºI—˜–€Éj€½5$ø=bÕŸ€˜–€s÷€Us0Ô 5= [€$Ÿ±²}ú—‚±²|j0ÔI>Us= $Ÿjj= [€UsI>g€0Ô 5+Ä|+Ä}€…€I>ô$ô$Y½5€˜–€g€g€s÷€±€Ûºçï1-Yô$ ŽÕŸ€Œa€[€= $Ÿ0ÔUs= ˜–€ÕŸ€Éj€½5€…[æ[æ$øçïhŒºtP$øô$=bhI—ô$Ûº¤Ë€±€ÕŸ€½5€ô$Y=bY7777aBUFRÆbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀ 0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@)2à`ÃPs÷€Œa€[€6–€s÷€Ï…YÝ[æO±O± Ž·€,€ž±˜–€Œa€Œa€·çïYž±ÃPÏ…Œa€·Ï…ªæž±ÛºÃPž±ž±˜–€Ï…Ï…·€,€6€ 56î€[€g€C#€[€€,€g€g€€,€g€ªæYtPtP€…Ý7GÝÝYçï·ž±·ÃPçïÏ…çïÃçïÛºÃhC|h˜ï[æ€çïô$ÃPªæÛºÏ…ÃP·OX€„€g€ÃPŒa€Œa€6î€6a€˜–€çïO±7G€çï ŽhŒº˜ïŒºhŒº·t˜ï7G€çïž±çïO±‚è¡PcÏÞh Žô$÷t²«?7777¤ËBUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀ40’I$’I$’I%$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¦¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUPUUUPUUUUUð aâ-˜ïŒº˜ï±YI—[æ Žçïô$Ûºô$ ŽI—%Q=»²²%Q1-1-UÌh˜ïhh=bI—tP[æ€çïÉj€ 5g€ۺ[æ[怅 ޱ ŽYÕŸ€±$øY1-I—çïçï¤Ë€Œa€Us0ÔUsUsÉj€çïtP=b1-˜–€€,€˜–€Œa€½5€±€ÛºY ޽5€±€Éj€½5€[€ 5$Ÿ+Ä~7 ‚±²|0Ô 5€,€±€Œa€I>UsUs= [€= Uss÷€Us= $Ÿ7 ú—ú—ú—ú—s€…‚7 € 5UsUsI>= g€I>I>I>I>= ˜–€ÕŸ€ÕŸ€±€±€jI>= I>s÷€$Ÿ7777aBUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀL0$’I$’I$”’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B©lkŸÊt­®ˆd)Ž„©msáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUUUUUUUUUUUUUUUUUUUUUUUUýàb¥}~¥}|= $Ÿjjj$Ÿg€= j[€0Ô€,€˜–€˜–€€,€I> 5~¥}|$Ÿ¤Ë€˜–€¤Ë€±€ÛºÏ…çï[æO±tP1-=b1- ŽçïYô$çïçïô$YI—ÉÃŒºO±ÃÏ…1- Ž1-tP€…½ŽÜèHÉÃÕø¥$hO±I—1-$øO±hÉÃtP€ô$çïÉjYçï ŽO±±Y‚%Q1†%QÕø¥$I—$øYçïۺυÀ…½Ž¥$=bçïÏ…Ûº½5Ãô$Ãɲ ç çÜ€…€Éj€¤Ë€Éj€˜–€OX€0Ô€,€Éj1-I—=bÃÛº½5€±€˜–€Œa€¤Ë€7777aBUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀ`0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’Ûm¶Ûm¶Ûm·`‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-Ž|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUPUUU@UUUUUUUUUUUUUUUUUð `Éj€ÕŸ€¤Ë€Œa€I>= $Ÿ 5 5+Ä+Ä| 5I>s÷€±€±€g€¤Ë€€,€s÷€€,€Œa€€,€[€€,€[€= 0Ôj0Ô 5= 0Ô+Ä~7 ‚±²|j0ÔUs[€€,€0Ôj0Ô= 0Ô$Ÿ= = $Ÿj+Ä~7 ú—ƒ+Ä| 5+Ä|$ŸI>ÛºÛº˜–€±€Éj€½5€¤Ë€ÕŸ€±€½5€çï Ž1-UÌ€…I—ÕŸ€Éj€¤Ë€ô$ÕŸ€¤Ë€˜–€±€Ûº[æUÌI—Ã$øUÌtP ŽtP€…$øÛºÕŸ€±€[€$Ÿ[€0Ôs÷€¤Ë€˜–€ô$hŒºUÌ1-$ø ŽYçïۺå$˜ï±YÕø‚²ô}èH˜ï˜ï€…€7777aBUFRöbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÂUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï{Þ÷½ï}ï{Þ÷½ï{Þ÷½ï{Þ÷€„!B„!B„!D!B„!B„!B†1ŒcÆ0Š!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýà^Ÿc n }Œ¾h-pOX€¤Ë1-Iðc ƾh.ŠlV`º(Ah‚è¡ n 'À » -PÖ O€0Ôja¨ÃP|(!‘Àf;à¤Ë€çïèHc ¡ ýà6î€zçï1†õˆ 'À » -P)2à'¬@OX€’|a¨ @ q°#`9ûÀs÷’Õ²>|( q° @@g€υŸ > ýà/M`ReÀ€,€Ï…1†d¸Ø~ð F0Àg€·$øèH“à¡ O€'¬@½5’Õ%ªé¬ ÓX™pð j 5I>a¨†  „€F0Àg€±‚²nèKTŒ0„€I>†GÛº·tbZKT?xýàj= 0Ôa¨zÄ L¸!‘ÀOX€ž±ô$7777€IBUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠ¥±ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUPUUUUUUUUUð `€,€˜–€½5€Éj ŽÃÃ1-=bÃô$ô$ ŽhUÌ$ø$ø$øÃI—=bÉj€Éj€±€¤Ë€½5€Éj€±€±€½5€Éj€¤Ë€±€½5€Œa€I>= I>[€Uss÷€¤Ë$ø=b$ø½5€Éj€ô$çïçïÕŸÃUÌâ-˜ï=bUÌhI—I—$ø1- Ž Žg€ۺ Ž ŽYÛºçï€,€Œa€½5€±€ÕŸ€ÛºÕŸ€çïŒa€UsUsUs$Ÿ 5+Ä~±²~±²|0Ôg€€,€g€Œa€s÷€Uss÷€Œa€±€ÕŸ€Éj€Œa€¤ËY0Ôj0ÔI>= ½5€€,€[€g€½5€ÛºÕŸ€½5€±€Éj€˜–€±€€,€˜–€˜–€±€±€¤Ë€±€7777X€BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë$0$’I$’I$’II$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ç>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUQUUUUUUUUUUUUUUUUUUUTUUUUUUU@ð `±€Œa€g€= 5±²|jUs½5Ã1-UÌ1-=bÃۺà ŽÃh$øÕøèH ç1†ô}˜ïI—I—ÃÛºÕŸ Ž1-˜ï1-1-ÕŸ€˜–€€,€s÷€±Ãô$ÉjÃ[æ=bÉj€˜–€[€I>I>¤Ë1-tPI— ŽÉj€€,€[€Us€,€[€½5€çïŒa€I>Us[€¤Ë€s÷€g€I>0Ô= Us€,€çïçïç€I>±²~7 ƒ+Ä~±²}ú—‚±²~±²| 5s÷€[€s÷€0Ô= Éj€˜–€±€Ûºô$$øtPhÃÛº½5€¤Ë€€,hYô$Éj€¤Ë1-à ŽY˜–€s÷€[ƒ+Ä}ú—ú—€7777X€BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë<0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×B2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUPUUUPUUUUUUUUUUUUUUð ` 5[€g€g€˜–€g€¤Ë€½5€½5€= ˜–€¤Ë€ÕŸ€Éj€˜–€±²|Œa€I>s÷€I>$Ÿ±²~7 ‚±²|j±²+Ä| 5$ŸI>= Us0ÔUs€,€I>= 0Ô±²}€…ú—sssƒ+Ä~7 ‚7 ƒ+Ä|j$Ÿjj0Ô0Ô$ŸŒa€€,€g€€,€I>j±²}€…ú—€…sú—€jÉj€ô$ÛºÃh=b[æ€ô$˜–€˜–€ç€¤Ë1-[ætP=b=b1-Y ŽYô$=bUÌtP€çï½5€ÕŸ€çï€,€¤Ë€€,1-ۺÀ…±YhUÌ$ø½5€˜–€±€¤Ë€ô$Ã=bÃY¤Ë€±€¤ËY¤Ë€7777X€BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËP0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’Im¶Ûm¶Ûm¶àŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2¥mpC!Lt%sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU@ýà`¤ËI— ޽5€ÉjI—Œº¥$¥$ŒºtP=bô$ô$ô$çï[怅˜ï Žô$çï¤Ë€[€0Ԥˀ[€˜–€Éj€Ûº±€¤Ë€¤Ë€Œa€g€= 0Ôj$ŸOX€¤Ë€Éj€[€I>[€g€g€€,€s÷€Ï…ô$ Ž$øÏ…˜–€g€$Ÿj 5j¥}~¥}~¥}|$Ÿ$Ÿ 5jOX€[€s÷€[€0Ô 5j[Ãô}€,€j$Ÿ 5= jI>¤ËY[怅tPO±O±=bŒºŒºŒº˜ïÉñY=bô$¤Ë€±€g€$Ÿ$Ÿ 5$ŸŒa€Ï…Ï…±€˜–€0ÔOX€0ÔI>OX€g€[€€,€= j}îbtP€7777X€BUFR&bÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËUU\ç9Îsœç9Îsœç9Îs­kZÖµ­kZÖµ­kZÖµ½ï{Þ÷½ï{Þ÷½ï{Þ÷Îsœç9Îsœç9Îsœç9Þ÷½ï{Þ÷½ï{Þ÷½ïzŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUQUUUUUTUUUUU@UUUUUUUUUUUUUð b±²~±²|±²|jŒa€Éj€½5€€,€˜–€¤Ë€¤Ë€s÷€[€˜–€˜–€g€Us0ÔI>$Ÿ[ƒ+Ä|j$Ÿ= I>çïÃÕŸ€Œa€¤Ë€½5€€,€€,€UsUsUsI>= I>[€€,€s÷€[€j+Ä+Ä}ú—€$Ÿ˜–UÌh¥$€çï= Us 5$Ÿ 5j 5I>0Ô= Éj€½5€±€Éj€¤Ë€= 5+Ä~7 ƒ+Ä|$Ÿ0Ôs÷€g€€,€g€€,€€,€€,€Œa€˜–€¤Ë€Éj€ÉjYÃÛº½5€¤Ë€€,€€,€s÷€s÷€[€¤Ë€˜–€€,€s÷€Œa€¤Ë€Éj€˜–€ÛºÉj€±€¤Ë€ÛºÉj€çïÕŸ Ž ŽYÕŸ€½5€±€Œa€¤Ë€ô$$øÕŸ€Ûº7777BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@0I$’I$’I$¤’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN•µÀ …1ж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðBžP`ù¢A @³Àá8@‘ßÀ‘ßÀ³ÁAA A @³ÀÎèÀ…ªÀ‘ßÀªIÀªIÀím@Õ@¶~Àm@À¶~ÁadÁ¶×Á†ÁOABàABà@³Àím@ímABàA†ÁAA†ªûÃ7]B·0Á×@ù¢A×AyÎÁBàAadÁyÎÁžmÂz'À+(@ªIÀá8@Õ@TÖÀ³À³Àm@ÀžÁBàAU/Á×@á8@ù¢@¶~ÀÎèÁ A*vAžmšB·0Ãz€Ãz€Â*ÏAU/ÀímAU/ÁAA*vA*vAª¢Á¶×ÁadÁ’8ÁžmÃ7]COÇBOnAÏAžÆÂC9AíÆAÏAÁá‘Ba½Ãó@©ƒC’AÏAÁAA†Á*vA†ÁíÆAíÆAÏAÂ*ÏC¾BžÆÂÛÏÂÏšÁùûA AžmÁà ÁžmÁU/Á6«A’8Ám™ÁyÎÁm™Âa½Âa½ÁO@á8@ù¢A6«A*vA×ABà@7777j€BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBX×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUTUUUUUUUUUUUUUUUPUUUETUð a¥$tP€ÕŸ€s÷‚1† ç ç˜ï=bÛºÛº ŽtPäˀ˜–€s÷€Us= = Uss÷€= UsUsŒa€˜–€±€UsI>$Ÿ±²~±²~±²~±²| 5 5jj0Ô= = = 0Ô0Ô= UsUs[€s÷€g€I>= $Ÿ$Ÿj$ŸUs½5$øY ŽçïÛºÛº½5€±€±€ÕŸ€Éj€ÛºÛºÃUÌ=bô$½5€[€[€[€g€g€±ÃÛºÉj€Éj€ÛºÛºÕŸ€½5€±€˜–€[€Us$Ÿ$Ÿ 5+Ä~7 ‚7 ú—‚7 ‚±²|I>I>I>0Ô$Ÿ0Ô0Ô= g€j= 5±²|$Ÿ0Ô0Ô0Ô$Ÿ+Ä|UsUs7777j€BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@00$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUTDUUUUUUUUUUUUU@AUUð `±€ÕŸ€¤Ë€€,€[€s÷€Œa€s÷€g€Usg€I>Uss÷€€,€I>$Ÿ= 0Ô[€˜–€Œa€g€s÷€s÷€s÷€Œa€g€[€€,€= Us±€Éj€s÷€˜–€ô$±€ÛºÉj€ÛºÉj€s÷€Us$Ÿ[€[€jú—ƒ+Ä| 5 5±²|j±²| 5$Ÿg€çïÛºUÌ Ž€,€±€ÛºŒa€±€Ûº$øÃÛºÛº±€±€ÕŸ€±€g€¤Ë€Éj€±€[€˜–€±€g€0Ôj 5jj 5$Ÿ= Us[€I>$Ÿ0ÔUs[€= Us€,€= $ŸUss÷€0Ôú—sƒ+Ä|j±²~±²|jg€ô$YÛºÕŸ€Éj€ÕŸ€çï7777j€BUFR¶bÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@D0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×B2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýà]ÏÞŸ¼?x øPýà= €,€çï²>鬦°@@†G[æ‚Ið“à 'À~ð!‘ÀC#€†GÃzk> @Ü ÓXð OX€¤Ë€½5zkŸ¼Ÿ¼Ð @ @j€,·tÐÝÐ ð 3á@^šÀ½51-Ð?x ‰h-PC#€ÌwÀÛº·tnèc |(¡ B@$Ÿg€·ÏÞc –¨¦°,@ ReÀ˜–I—1†Ä´ÆÐ6ËI—bZ“à ‰hŒ0 'ÀB@ 5jÃPèH¸Ø~ðã`„€Œa€ž±²ˆ –¨¦°2Z g€½5zkôÖÝÐ~ð„€&% 9ûÀ¤Ë·tc Æ-P6î€^šÀ¤Ëzk28 'ÀB@Ð&% ReÀ€,€7777ƒ+BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@X0 $’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»m¶Û`‹k€" c¡/„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `Œa€g€0Ô0ÔjI>Œa€çïh=bŒa€€,€[€çïs÷€€,€ô$Y€,€g€I>$Ÿ= $ŸUsÛºU̘ïâ-YÉj€±€½5€½5=bI—˜ïhY1-UÌŒºtPhÃUs= [€[€€,€˜–€çïÛºô$Éj€ÕŸ€½5€˜–€¤Ë€Œa€Œa€Ûº±€±€ô$Ûºô$çï±€s÷€˜–€$ŸI>€,€˜–€Œa€s÷€[€[€±€Œa€½5€±Y½5€Éj€ÕŸý5€Ûºg€Usg€½5€Œa€Œa€€,€I>= I>€,€Œa€¤Ë€˜–€˜–€Uss÷€I>I>[€g€I>0Ô$Ÿ 5+Ä+Ä|7 €…s€…€…€ 5j7777j€BUFR&bÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËBUUUUUUUUUU]ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½ï½ï{Þ÷½ï{Þ÷½ï{ÞðB„!B„!Bж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇB–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUUUUUUUUUUUUUUUUUUUUUUUUUð `0Ô$Ÿ= $Ÿ$Ÿ= 0ÔŒa€€,€˜–€˜–€½5€s÷€$Ÿú—ú—‚7 ‚±²|j7 €±²| 5 5j$Ÿ0Ô$Ÿ[€I>s÷€s÷€Uss÷€s÷€= j0Ô= s÷€Œa€±€çïçïçïÉj ŽÕŸ€ÉjUÌhY±€Œa€s÷YUÌÛºŒa€Œa€[€˜–€˜–€½5 Ž ŽÉj€±€¤Ë€±€ÕŸ€Ûºçï ŽUÌ1-$øÃ1-$øô$½5€˜–€¤Ë€Œa€˜–€s÷€ÕŸ€ÛºÛºô$½5€ÛºçïÛºÃô$ Ž¤Ë€¤Ë€½5ÃUÌ$øÛº€,€±€±€[€Œa€½5€Ûºô$Éj€¤Ë€Éj=b½5€½5€¤Ë Žô$ÛºÛºÃ7777BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€0$’I$’I$’II$’I$’I$’m¶Ûm¹$’I$’I$¶Ûm¶Ûm¶ÛmÛm¶Ûm¶Û`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†BÆT­®ˆd)Ž„©lk§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUEUUUUUUU@UUUUUUUUUUð a€…[æY$øô$hI—YÕŸ€¤Ë€˜–€±€˜–€g€Us˜–€€,€˜–€Œa€Œa€Œa€¤Ë€Œa€±€ô$ÛºÛº±€I>UsI>+Ä~±²~7 ‚±²~±²|0ÔUs= j 5jj$ŸUsg€€,€˜–€€,€j$Ÿ+Ä|$Ÿ 50Ôçïô}$ø±YÃÛº±€˜–€¤Ë€€,€˜–€s÷€Œa€½5€½5€Ûº¤Ë€˜–€s÷€€,€˜–€±€Éj€½5€¤Ë€˜–€I>j+Ä~7 ‚±²|= s÷€Éj€½5€±€¤Ë€±€±€ô$ÃÃà ŽÕŸ€˜–€Œa€g€Éj€¤Ë€0Ôj0Ôg€I>Us€,€¤Ë€¤Ë€±€˜–€¤Ë€½5€½5€ÛºÕŸ€Éj€¤Ë€¤Ë€±€7777€BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€ 0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛnÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ç>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUQUUUUUUUUUUUPUUUUUUUUUUUUUUUð `Éj€˜–€s÷€= 0Ô+Ä|j0ԤˀÉj€˜–€˜–€s÷€˜–€¤Ë€˜–€¤Ë€˜–€ÕŸ€ÕŸ€ÛºÛºÛºÕŸ€€,€[€0Ôs÷€€,€I>I>0Ô= [€g€[€s÷€€,€€,€g€€,€±€±€±€ÕŸ€Éj€ÕŸ€ÕŸ€Éj€€,€[€= $Ÿ+Ä~±²~7 ‚±²| 5$Ÿ 5$ŸjI>€,€0Ôjj0Ô$Ÿj 5+Ä~±²}ú—ú—‚±²|[€˜–€Éj€Éj€Œa€€,€g€˜–€¤Ë€¤Ë€Éj€ô$±€Œa€€,€Œa€¤Ë€g€$Ÿj$Ÿj€,€±€çï½5€ÛºÛº½5€½5€ô$ÕŸ€ô$ÕŸ€çï½5€±€Éj€Ûº¤Ë€I>jI>Us[€g€7777€BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€80$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUP@PUUUUð a=bUÌ=b=bYY Ž Ž$ø˜–€½5€Éj€½5€±€½5€ÕŸ€Éj€ÛºÕŸ€€,€s÷€s÷€s÷€˜–€¤Ë€½5€±€Éj€½5€±€ÛºY Ž ŽYÃI—Éj€±€˜–€±€±€±€s÷€s÷€= $Ÿ= g€˜–€¤Ë€¤Ë€Éj€¤Ë€ÕŸ€Ûº½5€ÕŸ€çïçï±€˜–€˜–€€,€€,€Œa€¤Ë€g€I>j0ÔjUs€,€[€˜–€˜–€±€s÷€I>Us[€˜–€g€0Ô0Ôg€g€՟€±€I>$Ÿú—‚±²|$Ÿ+Ä~7 ‚7 €j7 ‚7 ú—‚7 ‚±²}ú—ƒ+Ä~7 €$Ÿs÷€˜–€çïô$Y$ŸjUs¤Ë€¤Ë€g€Us[€Usg€7777€BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€L0$’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUTUUUQUUUUUUUUUUUEUUUUUð `s÷€Us€,€€,€g€g€g€s÷€±€¤Ë€s÷€I>g€$Ÿ0Ô0Ô[€g€g€[€[€= Us= [€$ŸUs0Ô$Ÿg€= I>g€j= +Ä}ú—€$ŸUsÉj€ÕŸ€€,€s÷€€,€Us¤Ë€Œa€±€½5€ÛºÉj€Éj€gƒ+Ä|g€g€UsI>Us€,€UsŒa€½5€çï Ž$ø¤Ë€s÷€˜–€s÷€€,€g€½5€Éj€s÷€= I>j$ŸUs= = [€ 5= ˜–€€,€g€= I>0Ô$Ÿ= I>0Ô0Ô= j 5+Ä|jj$Ÿ 50Ôú—€…€…€$ŸI>j[€[€g€Œa€€,€s÷€˜–€€,€Us[€I>$Ÿ7777€BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€`0 $’I$’I$’RI$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’Ûm¶Ûm¶Ûm·m¶Û`‹k€" c¡*[çÂ2+k€" c¡*sáN•µÀ …1Е-sáN•µÀ …1Е±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUAUUUUPUUAUUUUð b7 ‚±²}€…ú—€Œa€…‚±²| 57 ƒ+Ä}€…‚±²+Ä| 5+Ä|+Ä|±²|I>€,€çïÉj€$ŸUsg€$Ÿ±²}ú—ú—€ 5= [€g€[€[€0Ô$Ÿj7 ƒ+Ä|j= 5 5+Ä|Œas‚±²+Ä|= s÷€UsUs[€g€= Us0ÔUsI>j 5$ŸI>Us0Ô7 sss€…‚±²|½5€Éj€Ûº¤Ë€I>0Ô7 ƒ+Ä+Ä~7 ‚±²+Ä|jj+Ä+Ä|j7 €0Ô[€½5€ÕŸ€Œa€0Ô+Ä~±²~±²~±²~±²+Ä|j 5+Ä|g€I>Œa€Ûº€,€˜–€[€s÷€s÷€±€ô$ ŽI—ô$½5€7777€BUFR&bÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë‚UUUUUUUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï@„!B„!B„!D!B„!B„!B†1ŒcÆcÆ1Œcç9Îsœç9Îsœç9ÎpŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUUUPð `çïçïYI—UÌ[æ€ô$Œa€ 5 5±²}ú—€…s€O€…€Œa€O€O€Œa€…ú—ƒ+Ä+Ä}ú—ú—‚±²~7 ‚±²~7 ‚±²}ú—ú—ú—‚7 ‚7 ‚±²}ú—ú—‚±²~±²+Ä~±²~7 €…€O€Œa€Œas€…€…ú—€$Ÿ€,€= jUs±€j$Ÿ[€[€Usg€0ÔjI>Œa€Éj€€,€Éj€Œa€s÷€¤Ë€€,€= jjs÷€s÷€½5€€,€˜–€ÛºI>Usj0Ô$ŸI>I>Éj€½5€Ûºô$0ÔI>I>I> 5js÷€ÕŸ€ÕŸ€½5€s÷€g€˜–€[€0Ô+Ä~±²+Ä|$Ÿ$Ÿ7 s€Œa€Œa€Œass€Œa€Œa€Os€…€7777BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀ 0 $’I$’I$’RI$’I$’I$Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ý¶Û`‹k€" c¡*[çÂ2+k€" c¡*c\øFS¥mpC!Lt%LkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUð as€Œa‚7 ƒ+Ä}ú—€…‚7 ú—ú—€…€…ú—ú—ú—ú—€…€…ú—‚7 ‚±²~±²+Ä+Ä~7 ‚7 ú—€…ú—€…€…‚7 ƒ+Ä|$Ÿ[€¤Ë€I>jj 5j$Ÿ= $Ÿ$Ÿ$Ÿ0Ô$Ÿú—‚7 ‚7 ú—‚7 ‚±²|jg€՟€Œa€˜–€¤Ë€$Ÿ$Ÿ[UÌŒº=bçïÃÛº$ø€…UÌô$Éj€s÷€s÷€˜–€±€±€Œa€s÷€s÷€[€s÷€˜–€½5€¤Ë€ÕŸ€çï±€Éj€ÕŸ Ž=b=b=bŒa€˜–€½5€Œa€Éj€çïçïI—=b±€Éj$øçïtP¥$±Y€…€Éj€€,€s÷€Œa€˜–€ô$ô$Ûº[€UsI>$Ÿ$Ÿ€,€Œa€7777ÔBUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀ80I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’[m¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„­sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUUUUUUUUUUUUUUUUUUUUUUUUð `Éj€±€˜–€˜–€€,€±€Œa€Œa€[€UsŒa€Éj Žô$˜–€Œa€I>0Ô+Ä~±²+Ä|I>g€s÷€s÷€I>I>I>I>Uss÷€Us$Ÿj$ŸUsI>±€ÛºYçïg€Us0Ô[€[€$Ÿj$ŸUs$Ÿj$Ÿ0Ôs÷I—½5€çïÃUÌI—çïs÷€€,€= j0ÔI>Us€,€€,€s÷€Œa€˜–€Œa€½5€€,€Œa€Œa€Œa€˜–€€,€s÷€€,€Œa€çï¤Ë€[€= 5 5[€s÷€g€g€Us= = 0ÔUsUsI>I>I>= UsI>$Ÿ0Ô$Ÿ 50Ô= 0Ô= I>UsI>Us€,€g€˜–€g€g€Œa€7777ÔBUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀL0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUQUUUUUUU@ð `Œa€€,€±€Éj€½5€±€ÕŸ€Éj€±€±€Œa€g€€,€€,€˜–€g€g€s÷€g€€,€˜–€€,€€,€±€g€Us€,€ô$h ŽY Ž¤Ë€Us[€˜–€±€€,€g€€,€s÷€g€¤Ë€±€˜–€ÕŸÃ$ø±€Éj€ÛºÉj€ÛºÕŸ€ÕŸ€ÕŸ€¤Ë€I>0ÔI>g€g€[€g€g€€,€s÷€˜–€€,€€,€˜–€˜–€s÷€€,€Œa€çï1-[æ€ô$çï$øÛºÉj€±€€,€I>0Ôjj 5 5 5±²| 5 5I>g€€,€[€€, Ž Ž¤Ë€€,€½5€ÕŸ€ÛºY$øäˀ[€s÷€= $Ÿjj 5jg€I>j+Ä+Ä~7 €7777ÔBUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀd0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ …1Е±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUUUUUUUUUUUUUUð b±²~7 ‚7 ‚±²| 5$Ÿ$Ÿ 5$Ÿ0Ô+Ä| 5+Ä| 5I>I>0Ô7 ‚7 ‚7 ‚7 €I>UsI>UsUs0ÔI>I>Œa€ÕŸ€ÉjUÌ Ž€,€çïÃ=b½Ž±Y$ø¤Ë€j0ÔÉj€ô$=b$øg€0ÔI>g€Us½5€ÕŸ€Ûºô$Œa€ÕŸUÌ1†²1†ô$Œa€˜–€€,€[€€,€½5ÃÃô$ô$ô$˜–€ÕŸ€ÕŸ€±€ÕŸ€˜–€¤Ë€ÕŸYÛºÕŸ€çïÉj€˜–€[€$Ÿj[€½5I—$øÛº¤Ë€[€[€s÷€I>[€$Ÿs÷€[€= g˜ï‚t©Õø=bÕŸYô$ÕŸ€ÛºÛºô$tPUÌçï7777ÔBUFR&bÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÂUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï}ï{Þ÷½ï{Þ÷½ï{Þ÷€B„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ0Š¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTDUUUUUUUQUUUUPUUUTUUUPPUTUð `Œa€[€7 €+Ä|0Ô±²|= g€UsŒa€Œa€[€j 5±²+Ä|s÷€˜–€½5€Éj€˜–€g€I>jj 5$ŸUs€,€±€Us[€s÷€0Ô$Ÿ= ˜–€= ±²|g€˜–€ÕŸ€½5€±€±€€,€ 5$Ÿ€,€Œa€s÷€s÷€Œa€€,€g€$Ÿ 5+Ä~±²|I>Œa€€,€Œa€Œa€Usj$Ÿ 50Ô= 0Ô 5+Ä|$ŸI>0Ô±²|±²~±²|jŒa€Éj€½5€g€= 5±²+Ä+Ä| 5$Ÿ+Ä+Ä|j 5±²}ú—ú—ú—ss€…€$ŸUs= = j 5+Ä| 5 5j7777BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUQTTU@TUUUTUUQUUUTUUUTð `= 5j 5 5±²|jUsgƒ+Ä~7 ú—‚7 ‚7 ú—ú—ú—ú—‚7 ú—‚±²~±²|$Ÿj7 €0Ô[€ 57 ‚±²|+Ä~7 ƒ+Ä| 57 ‚7 ‚±²~±²~7 ƒ+Ä|0Ô±²}ú—‚±²}€…€…ú—€$Ÿg€I>0ÔI>I>0Ô$ŸI>I>[€€,€0Ô$Ÿ$Ÿ 5j 57 ‚7 ú—‚7 ‚±²| 5€,€Éj€Ûºs÷€$Ÿ 5$Ÿ 5±²| 5$ŸI>€,€s÷€[€ 5I>UsI>s÷€½5€çï[æ€g€ 5+Ä|$Ÿ= 0Ô0Ô= I>I>= UsUs[€ 5 5+Ä~±²|[€ô$I—7777—BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë(0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%LkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž…-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUQUUUUUUUUUUUUUTUUUUUUUUUUUUUUð atP€±€j+Ä|jj= $Ÿ$Ÿ˜–€[€0Ô 5±²|= ±²|I>[€½5€çïYçï€,€s÷€= Œa€= Ûº¤Ë€[€[€ô$±€Œa€€,€ÛºUÌ¥$€ÕŸ ŽŒº½ŽŒº€çïÛºÕŸ€Œa€I>I>Us= 0Ô0Ôjs÷€g€Œa€I>g€Us 5j 5±²+Ä|$Ÿj 5 5$Ÿ$Ÿ$Ÿj 5 5[€Uss÷€Œa€¤Ë€½5€Œa€I>Éj€¤Ë€±€€,€€,€½5€çïÉj€Œa€±€Œa€±€±€½5€çï1-ô$ÕŸ€ÕŸÃ ŽÉj€˜–€˜–€Œa€€,€g€€,€Œa€ÉjYYÕŸ€±€Ûºçï½5€Ûº1-7777—BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë<0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUPTUUUPUQETPUTð `ÛºÕŸ€Éj€½5€½5€ÕŸ€½5€˜–€s÷€€,€˜–€¤Ë€½5YUÌô$=bI—ÕŸ€ô$çïÉj€¤Ë€Œa€±€Us€,€[€€,€s÷€g€[€[€I>[€s÷€ÉjÃÉÀ[€$Ÿ 5 50Ôj 5 5$Ÿ 5 5+Ä~7 ‚±²~7 sú—ƒ+Ä|j$Ÿjjj+Ä|I>= $Ÿ= = = = = = = 0Ô$Ÿ= ú—€…‚±²| 5I>I>I>Usj 5 5±²|+Ä| 5j$ŸUsj+Ä|Œa€$Ÿú—ú—s€…s‚7 €…‚7 ‚7 €…ú—€+Ä+Ä|0ÔI>s÷€çïÕŸ€g‚±²|7777—BUFRæbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËT0I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ …1Е-sáN•µÀ …1Е-Ž|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUQUð `€,€[€g€½5€Éj$øÕø½Ž€Éj€˜–€ô$[€€,€çïÉj€Éj€ô$Œa€…€Usg€0Ô 50Ô€,€˜–€½5€¤ËÃh‚ht‚½ç[怽5€$Ÿ= ˜–€= ÕŸ€g€0Ô€,€±Õø‚%Q$øI—¤Ë€s÷€s÷€¤Ë€Ûºô$ÛºÉj€½5€çï Ž$ø$ø$øY=bÉj€çïà Žô$YÕŸ€½5€Ûº±€s÷€[€˜–€ÕŸ€Ûº1-[æ€ô$¤Ë€g€s÷€[€˜–€Éj€€,€Œa€€,€±€˜–€s÷€g€0Ô 5ú—‚7 €0Ô[€s÷€Œa€s÷€Uss÷€g€Œa€Œa€˜–€Œa€= = g€I>$Ÿj+Ä|j±²~±²~±²|= €,€€,€€,€g€7777—BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ëh0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¦5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUAUAUTUUUUEUUUUUUUUUUUUUUUð `Œa€Us[€Œa€g€UsUs$ŸI>s÷€Œa€€,€[€ 5 5I>$Ÿ[€[€Us0Ô±²+Ä|0Ô$Ÿ+Ä~±²| 5$Ÿ¤Ë€€,€½5€€,€j+Ä~7 ‚±²}ú—‚±²+Ä|0Ô$Ÿ0Ô$Ÿ$Ÿ 5$Ÿ$Ÿ0Ô[€g€s÷€€,€€,€€,€= $Ÿ0Ô7 €0ÔŒa€½5€Éj€˜–€Œa€Ûºçïô$ô$çïçïÛºY ŽYô$Éj€[€g€¤Ë€±€Éj€Éj€ÉjÃtP$øÕŸ€ô$±€Éj€çïçï1-½Ž±YYÉj€¤Ë€½5€€,€[€€,€€,€s÷€€,€˜–€Éj€ÛºYÛº½5€ÕŸ€½5€ÛºÕŸ€Éj€çï¤Ë€ÕŸ€7777—BUFRöbÿ« fË2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_{ÞðB„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1ŒcB„!B„!B„!JP‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýà]Ã1†ˆÈ€ 'À'¬@0Ô0ÔÃP&\Èàýà&% dµAY28 ëÐ#`] §ØÁO±‚è¡2ê }ŒŒ0#`6î€z$ø·t>¡ ÈàýàF0À†Gô$èHÐ|(?x,@ ^šÀ˜–ÏÞŸ¼é¬È øPO€^šÀs÷€zÃP† õˆ ë 5 50Ô’|a¨Ð 'ÀýàF0ÀÛº²dÆ = €,€ÛºŸ ÄKTÈà'¬@OX€§ØÁI— “àÈO€&% lV`ÌwÁ½Ž‚·Íõˆ L¸Ö w@9ûÀ^šÀ¤Ë€Ï…Ÿ ˆŒ0!‘ÀF0À’|ô$²28ÝÐ øP 3á@^šÀÏ…1†Ä´dp~ðð ã`jj7777UBUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@0’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶6”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUU@UUUUUUUUUUUUUUUUUUTUTUUð `$Ÿ0Ô±€ô$ô$çïÉj€ÕŸ€Éj€€,€Éj€ô$çïŒa€Éj€˜–€˜–€s÷€Œa€Us0Ô±²~±²~7 €…‚7 ‚±²|j= = 0ÔUsUsUsUsÉj€ÕŸYÕŸ€ÉjYŒa€s÷€Œa€g€0ÔUs€,€±€ÛºYçï½5€Éj€ÕŸ€€,€Éj€ÕŸ1-ô$¤Ë€Éj€Éj€s÷€€,€I>I>Us= 5= Œa€½5€˜–€s÷€s÷€[€[€s÷€[€g€˜–€±€˜–Ã¥$€…€…[æUÌ=bÃ Ž€,€g€€,€¤Ë€¤Ë€˜–€g€Us= +Ä}ú—ƒ+Ä|s÷€s÷€s÷€±€½5€I>I>Us= +Ä+Ä|j 5 5UsI—1-1-Ãô$¤Ë€½5€7777ã`BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@,0$’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUU@UUUUUUUUUU&% `€,€¤Ë€s÷€Ï…7G ŽtPŒº7G+€ô$Ûº˜–€[€C#€6,€ªæÏ…ÃP[€g€$Ÿ6î€C#€€,€ªæOX€Œa€s÷€[€˜–€·Œa€˜–€OX€C#€€,€Œa€Œa€¤Ë€ªæY+C|€Ûº7GYC|tP÷Ï…±Y€…˜ïŒºC|$øY·ÃP¤Ë€ªæ$ø€…‚ô$ÛºŒa€OX€j6î€C#€ÃP ŽäˀOX€ 5úð~Ì‚úð~€Þ~Ì‚úð|¤Ë€ªæô$Y ŽÃPô$ô$Ã$øC|Ã$ø+ ŽÏ…ÛºŒa€˜–€çï··ªæÛºÛºÛºÛºÏ…ÃPÃPçïçïÃYÃÃPÛºç€s÷€7777ã`BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶Ý¶Û`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `€,€g€I>[€I>$Ÿ$Ÿj0Ô0Ô= I>= UsŒa€½5€Œa€Ûºçï1-€…€½5€˜–€g€= 5±²~±²+Ä|I>Éj€Éj€Œa€€,€[€[€Us= Uss÷€Œa€[€= $Ÿj+Ä}ú—€…ƒ+Ä}ú—ú—‚±²|= Œa€Œa€€,€s÷€g€0Ô= = = s÷€s÷€Us±€[€g€I>$Ÿjj$ŸI>±€ô$Ã$øçï¤Ë€Œa€Œa€½5€Ûº$øI—˜ï½ŽŒºŒº˜ïÉÀ… ŽYÉj€Éj€±€¤Ë€±€±€¤Ë€Éj€Ûº ŽÉj$øUÌ$øI—$øYYçïô$Éj€½5€€,€Usg€˜–€¤Ë€Éj€7777ã`BUFRæbÿ« fË  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë@X0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Ûm¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž…±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUTUUUUUUUUUTUUUUUUUð `½5€ÕŸ€ÕŸ€Éj€˜–€ÕŸ€Éj€ÛºçïçïÛºÕŸ€ÕŸ€¤Ë€˜–€€,€I>Éj€ÕŸ€Éj€±€±€±€Œa€¤Ë€€,€s÷€[€[€[€½5€˜–€g€Œa€ÕŸ€½5€Œa€Œa€s÷€Us= Us 57 s‚7 ‚±²|$Ÿ$Ÿ0Ô$Ÿj 5= = 0ÔI>¤Ë€¤Ë€[€0ÔI>[€s÷€€,€±€½5€½5€±€[€[€= Usg€g€s÷€€,€€,€s÷€s÷€I>j±²}€…€…€…€…ú—€js÷YI—$øô$ Ž Ž Ž$øÃ$ø ŽYYô$çïçïs÷ƒ+Ä~7 € 5UsŒa€Œa€[€I>= $ŸI>0Ô$ŸUs€,€½5€7777ã`BUFR&bÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËBUUUUUUUUUUUU]kZÖ·½ï{Þ÷½ï{Þ÷½ï{ÞùÎsœç9Îsœç9Îsœç;Þ÷½ï{Þ÷½ï{Þ÷½ï@„!B„!B„!D ‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUDUUUUUUUUUUUUUUUUU@UUUUUUUPð `˜–€[€Us0Ô$Ÿ+Ä|+Ä}€…‚±²| 5g€±€Éj€ÕŸ€¤Ë€¤Ë€±€½5€¤Ë€˜–€ÛºYÕŸ€ô$Ûº±€Éj€ô$ô$Éj€½5€±€±€½5€¤Ë€¤Ë€ô$Yô$Ãô$YçïÛº ŽI—hUÌ[æI—UÌI— ŽÛºÕŸ€ÕŸ€½5€±€¤Ë€ÉjI—=b Žs÷€[€€,€±€±€±€ÛºÉj€ÕŸ€±€g€I>[€= j0Ô€…€…ú—‚±²~±²}ú—‚7 ‚±²~7 ‚±²}ú—€…ú—ú—€jg€ô$ÛºçïŒa€Us0Ô$ŸjUsÕŸ€Ûºô$Œa€€,€UsI>= [€€,€ÛºYô$±€Œa€s÷€Us 57 ‚±²|7777BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€ 0’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥²S¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUUUUUUUTUUUUPUUUUEUUð aú—ú—ƒ+Ä|UsÕŸY±€½5€ÕŸ€¤Ë€˜–€˜–€ÕŸ€½5€ÕŸ€±€˜–€Œa€€,€g€I>±²}€…€…€Œa€Œa€…‚7 €Us€,€±€g€Us= = ±€ô$ÕŸ€Éj€˜–€I>= Us= $Ÿg€Œa€Éj€Éj€½5€¤Ë€s÷€Us€,€[€[€±€ô$$øI—Yçï±€s÷€j 5 5+Ä~±²+Ä| 5s÷€Œa€€,€s÷€€,€€,€Œa€¤Ë€±€±€½5€Œa€s÷€g€s÷€g€= j 5+Ä~±²+Ä| 5g€˜–€½5€ÕŸ€±€¤Ë€¤Ë€±€½5€¤Ë€½5€ÕŸ€€,€€,€Œa€s÷€UsUsj+Ä|$Ÿ7 ‚7 ƒ+Ä|I>Us€,€€,€Œa€Œa€s÷€g€s÷€7777ºBUFRÆbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€ 0I$’I$’I$’’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶àŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ `€,€˜–€Ï…Y˜–€±€[€[€[€C#€= $Ÿ 5s÷YÃ1- ŽÏ…s÷€€,€s÷€s÷€± ŽC|hC|$ø¤Ë€Ï…Ï…˜–YÃP¤Ë€¤Ë€¤Ë ŽçïYÃP¤Ë€±€ÛºYhŒº€…½ŽŒºO±tPŒº€ô$Ûº€,€Œa€Œa€Œa€˜–€¤Ë€˜–€s÷€€,€±$ø[æ[æ1-ɲܱY€çï€,€[€OX€OX€$Ÿ0Ô0ÔgÂtP[æO±1-çï Žçï½5Yô$$ø1-C|€Ï…˜–€˜–€[€C#€j$Ÿ= $Ÿ$ŸOX1-±Y¥$$ø$ø$øC|$ø[æh€…½Ž‚²¥$[æô}²ÉÃ½Ž€7777UsBUFRÆbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€80I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýàa±Y˜ïtP1-Éj€[€= I>s÷€€,€s÷€¤Ë Ž$ø=b¥$ÉÃèHÕøô}ô}²˜ï ޽5€s÷€= 5OX€¤Ë€˜–€˜–€OX€0ÔI>OX€[€= [€Ï… ŽY$ø$øçïçïÉj€Œa€˜–€€,€€,€OX€Œa€ÛºYô$Éj€ô$Ï…Ï…çïÉj$øÃ Žô$½5€±€Œa€g€I>= I>$ŸjOX€˜–YÉj€¤Ë€±€½5€¤Ë€±€çïÃŒa€Ï…=b¤Ë€I>j 5$Ÿ 5OX€½5 Ž1-ÃÛº±€Œa€¤Ë€€,€¤Ë€ÉjYÛº¤Ë€±$ø1-ô$¤Ë€[€[€g€s÷€I>Œa€½5€çïô$çïÏ…7777UsBUFRæbÿ« fË  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€L0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5ÐŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUEUUUð `Ûº±€¤Ë€Éj€ô$=bI—$ø$øI—1-ÕŸ€€,€[€Œa€¤Ë€€,€±€ÕŸ=b1-=b$ø=b½5€s÷€Œa€˜–€˜–€çïÛºÛº Žçïô$à Žô$ Žç€¤Ë€Éj€ÕŸ$ø¥$‚ôÖ$ø[€Œa€±€çïô$=bUÌ$ø$øÃ=b ŽÉj€Œa€Éj€Œa€€,€€,€¤Ë€½5€¤Ë€s÷€Œa€˜–€¤Ë€€,€Œa€€,€ô$Ã1-ô$ô$çïÕŸ€ÕŸ€€,€I>= 0Ô$ŸI>±€ô$ÃYÕŸ€½5€ÛºÛº ŽI—I—UÌ1-ô$ÛºÉj€¤Ë€s÷€= $Ÿ$Ÿ±²|= Uss÷€±€€,€[€Usg€€,€€,€g€I>= 7777ºBUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë€`0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `I>$Ÿ$Ÿjj[€= I>Œa€½5Y½5€Œa€g€g€g€€,€€,€±€ÕŸh1-ÕŸ€¤Ë€Œa€[€I>+Ä|+Ä~±²+Ä| 5[€±€½5€½5€Éj€ÕŸ€ÛºYÉj€çïô$çïÕŸ€½5€½5€ÕŸ€½5€g€€,€s÷€I>= +Ä|$Ÿ˜–€¤Ë€ô$ç€€,€g€½5€½5 Ž1-UÌUÌI—I—=b1-Ã Ž ŽçïYÛºÉj€ÕŸ€çïÉjI—h[æ€çïÕŸ ޤË$øI—=bh[怅€ô$Éj€€,€Œa€g€[€= I>I>Uss÷€Ûº˜ï$ø[€g€s÷€€,€¤Ë=b$øÃ=bI—Yô$ô$çï±€Éj€7777ºBUFRöbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë‚UUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï{Þ÷½÷½ï{Þ÷½ï{Þ÷½ï{ÀB„!B„!B„"„!B„!B„!CÆ1ŒcÆ0ŠB˜èJ–ƹðŒ§JÚà†B˜èJ˜×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@= \I>ÃPèHõˆ 'À&% „€[òĴ » „€3á@X€@˜–Ó.é¬ ‰h¦°/M`X€@˜–€çïn6&\~ðw@I>Œah‚·Í&\È!‘À= mݽ5b²d?x q°ð $Ÿ 5I>ô$Ið“à ëã`@@±Ã%ªÄ´ ÓX™p/M`X€@˜–1-ôÖ&\ ‰hB@O€ 5ž±²&\B@-P/M`g€ۺYôÖ|(~ðw@2Z dµ@˜–1-²dõˆ 'À 'Àjz$øKT ÓXÐýàF0ÀŒaÓ.ˆ L¸&% dµ@½5ÃÄKT L¸-P/M`LK@ŒabÄ|(#`6î€3á@ 57777=BUFR¶bÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀ0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS SçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@)2à\ q°#Û°F0ÀnÀÏ…Ÿ ÐÈ\À*¹€g€υ·t>€ øP\Àð @@[€Ï…bZ> øP#`F0ÀnÁ Ž1†nè€ » j3á@g€ۺ·tÐöìE#`9ûÀ€,ÃèHd }ŒE-pZàÀBÁ¥$ƒ >Æ X”Èà#Û°@@g€υn6>¡ #`@@€,C|ƒ >Æ ß4Œ0#`@@€,€ÛºÏÞŸ¼€ 5\À F0Àž±=bzÄW0 øPð = †G Ž28ÈÈà#`3á@a¨·† «˜|(B@ã`*¹€OX€ž±ÃzÄ X”w@9ûÀmÝô$28ÆÈà%bPF0ÀnÁ+€7777&BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀ$0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUEýàa[æ1-ô$Yۺυ˜–€˜–€½5€˜–€½5€½5€Éj€½5€Éj€Éj€Ï…Ï…Ï…çïÛºÛº½5€Éj€Ï…Ï…±€½5€¤Ë€Œa€I>OX€€,€Œa€½5€±€Œa€s÷€s÷€g€s÷€g€g€€,€s÷€OX€g€g€[€OX€[€[€[€OX€[€[€Œa€¤Ë€˜–€s÷€s÷€€,€˜–€½5€±€±€½5€Éj€Éj€Ï…ÛºçïÛºÛºÉj€Ï…½5€±€±€¤Ë€¤Ë€Ï…Ã=bYÏ…çï Ž1-YÃ1-$øYçïÛºô$ô$ô$ Ž Ž ޽5€½5€½5€½5€Ûºçï1-[æ ŽYô$$øçïÛº ŽYÉj€s÷€˜–€s÷€$Ÿ|I>7777î€BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀ<0 $’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÆS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUAUUUUUUUUUUUUUUUUUUUUUUUUUð `½5Y1-çïçï½5€Éj€½5€ÉjY Žô$Ûº˜–€½5€¤Ë€€,€= 0Ôj7 ƒ+Ä|j˜–ÃYô$ÃYI—[æI—1-1-UÌ1-$øô$Ûº±€˜–€Us= [€€,€ô$=bI—1-ô$ÕŸ ŽÉj€ÛºÃ=b$øÃÃY Ž ŽÕŸ€ÕŸ€½5€ÕŸ€ÕŸ€Éj€ÕŸ€ô$UÌI—UÌ$øYô$ÕŸ€ô$Ã1-Ã1-=b$øY˜–€g€I>I>= +Ä}ú—€…ú—€0Ô= I>[€I>[€[€€,€½5€ô$Ãô$çïÕŸ€±€Éj€ÕŸ€Éj€Éj€Éj€Éj€±€¤Ë€±€çïÃ1-çïÕŸ€ô$ô$Éj€7777î€BUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÀP0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc_Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUPUUUUð a Ž$øUÌ¥$ÕøUÌ1-1-Ûº¤Ë€g€Usg€I>= g€½5€ÕŸ€ô$ÕŸ€ô$1-$ø Ž=b=b$øô$ô$Éj€€,€˜–€˜–€[€s÷€Œa€Uss÷€¤Ë€çïô$Ã1-à ŽY ŽÃUÌUÌUÌUÌ€…ŒºUÌ=bÃÉj€ÕŸ€¤Ë€€,€€,€€,€±YçïÉj€Éj€Éj€½5€±€ÕŸ€ÕŸ€ÛºYçïÉj€Éj€±€€,€I>I> 5= g€ÉjYÕŸ€½5€Éj€½5€±€ÕŸ€ÕŸ€½5€˜–€Œa€Œa€s÷€[€Usj7 ú—ú—ƒ+Ä|[€çïà ŽYYô$Œa€ÕŸ€çïÛº±€¤Ë€¤Ë€€,€±€¤Ë€½5€7777î€BUFR&bÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËÂUU\ç9Îsœç9Îsœç9ÎskZÖµ­kZÖµ­kZÖµ­ï{Þ÷½ï{Þ÷½ï{Þ÷Îsœç9Îsœç9Îsœç9Þ÷½ï{Þ÷½ï{Þ÷½ïzŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUUUUUUUUUUUUUUUUUUUUUUUUUUU `Ï… 5Z|j™H|[€= g€$ŸjOX€Œa€s÷€C#€¤Ë€g€ۺ±€˜–€s÷€ÃPOX‚6‚6â-‚6â-ƒZ|OX€g€= ¤Ë€s÷€C#€˜–€g€g€Œa€±€ÃP½5€ÃP±€[€€,€Ï… Ž ޱ€= 0Ô0ÔC#€s÷€€,€€,€€,€˜–€±€±€±€±€¤Ë€˜–€˜–€˜–€˜–€˜–€Œa€Œa€¤Ë€˜–€¤Ë€Œa€€,€€,€¤Ë€¤Ë€˜–€Œa€¤Ë€±€ÃPÃPÏ…çïô$ô$ô$ô$çïÃP½5€½5Y$ø1-ÃÛº¤Ë€ÃPô$ô$Y$øYÛºÃP½5€Ûº½5€±€½5€ÃP±€ÃP½5Y$ø1- ŽYYô$Ï…±€7777BUFR¶bÿ« fË  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ж5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]’ÕÄ&\ -P5gàjÏÀÛºÏÞŸ¼ÝÐ~ðw@6î€mÝÛºèHV~é¬ ÓX¦°)2àLK@Œa€çï²dÈŒ0,@ X€@ŒaI—“.&\ L¸Ð)2àLK@ŒaI—1†Ä´  ,@ X€@Œa€Ï…ÏÞdÈŒ0)2àX€@±I—“.Ä´ ‰hŒ0&% F0Às÷bbZc Ðã`F0À¤ËI—“.dÈ&% X€@½5’ÕÐdpB@-P2Z F0À= ’|a¨a¨ÃP† ã`-ÆÁYIð“.Ä´ ‰hŒ0ã`ReÀÕŸ1-bZŸ¼“à øPð $Ÿ$ŸI>ô$†  'À)2àmÝ Ž·t“.?x Yøw@/M`LK@Œa€7777PBUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðBU@ìp`§@„r@œÜ@§@„r@l@_Ó@Sž@MƒÀSž@_Ó@l@§@œÜ@©@„r@œÜ@œÜ@Ͱ@µF@ÓÊÀßÿÀÁ{@Á{@Ͱ@Ͱ@ÓÊÀøiÀøiÀøiÁžÁžÁžÁžÀøiÀßÿÀßÿÀßÿÀì4ÁžÁ)=ÁÓÁ5rÁMÜÁS÷A‘A‘Ax–Ax–A`,AMÜÁS÷A„ËAx–A„ËA`,A`,A‘Ax–AÎ AàXÁàXÂlºBµøB…$BBÁÁÔA©jAÚ>B,ÂN5ÁìÁÁÔAøÂÂBÁøÂÁøÂÁÎ AÎ A„ËAžÀøiÀøiÀÓÊÁ)=ÁA§Á©jA©jB÷Â5ËÂlºB…$AøÂÁ5BŽC)ïÀS Ä ˜Ã…}CNŽÂÚ—BÚ—BÎbBZjÁ5AÁÔBlºB`…BÚ—BÂ-Bà±ÂÎbBlºBBÁàXÁx–AS÷AS÷A`,A‘A„ËA5A`,AS÷A5rÀ7777PBUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ë00$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠ2ÇBT¶6”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUU@UUUTUUUUUUTUUUPð a1-$ø1-I—tP[æUÌI—=b$øô$Ûºô$çï±€˜–€±€¤Ë€€,€= j7 ƒ+Ä~7 ‚7 €€,€Ûº=bI—I—1-çï Žçï1-1-[æ$øY±€˜–€[€ 5€…‚±²}€…€…€…ú—€g€¤Ë€Éj€Éj€g€¤Ë€s÷€= ½5€€,€€,€Us$Ÿ 5±²~±²}ú—‚±²~7 s€Œaú—‚7 €0Ô[€g€s÷€Us0Ô$Ÿ0Ô0ÔUs˜–€[€Us= I>= 5±²}ú—s€Œa€…ú—‚7 € 5j 5j 5j$Ÿ0Ô$Ÿ= I>$Ÿ$Ÿj±²~±²~7 ú—ú—€…€…ú—‚±²+Ä+Ä| 5$ŸI>7777PBUFRæbÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËD0$’I$’I$’JI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×B2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `$ŸUsUsUsg€s÷€Us˜–€˜–€Œa€Œa€€,€±€½5€±€±€½5€ô$ ŽI—1-tP1-=bI—I—UÌ[æUÌhh=b1-$øÃÃ$øYÃÃ$ø$ø$øÃ1-hUÌUÌ$ø$øYYÃ1-YÕŸ€s÷€Us 5j7 ‚7 ú—€€,€çïUÌhI—UÌ ŽÃ1-tPŒº˜ï[æ[æ=b1-Ãà Ž$ø±€[€I>Us¤Ë€Ûº$øÃÃYÕŸ€ÛºÛºYY$øÃ Ž Žô$ô$çïÕŸ€Ûº½5€½5€±€Éj€ÕŸ€çïY$øY ŽçïY1-I—tP€…=bUÌ$ø½5€7777PBUFR¶bÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËX0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]I—Ÿ IðÐ @ @€j’|ÏÞ&\ ÓX¦°5gàdµ@Éjb%ªÈ  q°ð ^šÀÉjI—ÏÞd?x øPã`*¹€UsYôÖÆ¾h.ŠI>X€@½5‚1†Ÿ¼ÝÐ » !‘À= jÏÀçïÏÞÐ?x –¨ ð X€@ÉjbÄŸ¼¸Ø¡ B@-ÆÀ0ÔI>$ødÆŒ0/M`^šÀ¤Ë€çï$ø† † €I>I—“.?x ÓX„€,@ LK@ô$«?c 'À\À&% I>˜–$øIðÄ´ÆŒ0³ð5gàjÏÀÉjèH28 ë¸+|ÐLK@zÕŸ‚Iðõˆ L¸ C#€ReÀ˜–ÃbZc |( 'ÀO€jI>7777$BUFR&bÿ« fË 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ËUUUUUUUUTD»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»]ï{Þ÷½ï{Þ÷½ïœç9Îsœç9Îsœç9Îs½ï{Þ÷½ï{Þ÷½ï{Þ÷Þ÷½ï{Þ÷½ï{Þ÷½ïx!B„!BŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k„C!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@3á@XÐB@UsÃPW0jmÝÏÞÝÐw@˜–‚1†“àj€,‚²?xj= a¨jUÌÝÐ)2àÕŸƒÐ –¨ýàa¨²Æ)2às÷UÌÐO€a¨† ÝÐjUsô$Ið 'Àj’| @ 50ÔÃP“àB@I>† ÈýàI>ÃPÐB@$Ÿa¨† €$Ÿ0Ô0ÔÃP @ 5a¨Ið 'À$ŸÃPÐB@= ÃP @ 5$Ÿ’| @ 5$Ÿ’|Ið€ja¨†  50Ôô$ÐB@0Ôô$ÐjmÝèHW0O€I>† “à 5ja¨ 'À= $øÝÐ5gàáÔƒ%ª Yø;‚`½5€7777BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@0I$’I$’I$¤’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`ŠøFS¥mpC!Lt%Kc]N•µÀ …1ЗÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUQUUUUð aYÕŸ€½5€Éj€½5€¤Ë€±€¤Ë€¤Ë€Œa€˜–€˜–€˜–€¤Ë€½5€ÕŸ ŽYà Ž$ø$ø$ø$øáÔ€ÕŸ€áÔ€çïô$½5€ÕŸ€ÕŸ€¤Ë€Éj€Éj€±€ô$ Ž ŽçïÕŸ€Éj€ÕŸ€áÔ€±€ÕŸ€ô$çïÉj€s÷€a¨˜–€g€g€s÷€€,€½5€±€±€˜–€¤Ë€½5€ÕŸ€Éj€ÕŸ€çïÉj€çïáÔ€áÔ€Éj€½5€Éj€±€¤Ë€½5€¤Ë€¤Ë€±€¤Ë€±€½5€çïÉj€½5€½5€±€Œa€€,€s÷€g€= = $Ÿ0Ô= j 5+Ä| 5+Ä+Ä+Ä+Ä+Ä+Ä+Ä|ja¨a¨s÷€s÷€Œa€¤Ë€áÔ€áÔ$øçïÃYŒa€Usa¨±²+Ä~±²+Ä|7777èBUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@ 0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUTUUUUUUUUUUPUUT@QUUð ` 5= a¨€,€g€g€g€I>˜–€±€˜–€¤Ë€a¨I>0Ôj±²~±²}ú—ú—‚7 ‚7 ‚7 ƒ+Ä|j¤Ë€ô$Éj€Éj€Éj€çïçïáÔ€áÔÃYÕŸ€¤Ë€s÷€€,€a¨0Ô+Ä+Ä+Ä~7 ƒ+Ä| 5€,b=b Ž Ž ŽçïÃ$øÃb1-Ã1-ÃÃà Žý5€= áÔÃ Ž ŽáÔ€½5€Éj€áÔ€Éj€Œa€s÷€Œa€˜–€˜–€˜–€Œa€a¨a¨$Ÿ7 ‚7 €…€…€…€…‚±²|jUs€,€€,€g€Us= UsŒa€Éj€¤Ë€g€= $Ÿ+Ä|±²~7 ‚±²|±²|= Œa€¤Ë€¤Ë€¤Ë€¤Ë€±€çï7777èBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@40 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUDUUUUUUUUUUUUUUUUUUUUUUUUUUUð `±€ÕŸ€½5€˜–€g€UsI>0Ôj+Ä|+Ä}ú—€…ú—€…‚7 ƒ+Ä| 5 5j= I>a¨g€Œa€g€g€˜–€Éj€ÕŸ€çï½5€áÔ€áÔ€½5€±€½5€±€çïô$Ãô$Y ŽÃ1-$ø$ø Ž Ž Ž$ø Ž1-çïç€±€Œa€Œa€Œa€Œa€˜–€€,€¤Ë€ÕŸ€±€Éj€Éj€¤ËYô$çïáÔ€çïYY ŽÃ$ø$øÃ$øÃY$ø1-Ãçï ŽçïY$øbUÌI—I—1-=bn6n6$øÃÃY ŽÕŸ€¤Ë€±€Éj€Éj€½5€±€Œa€±€˜–€¤Ë€½5€Éj€çïYY$øI—UÌ=b7777èBUFRöbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@L@"""""""""""#33333fffffwwwwwwwwwwwwˆˆˆˆˆ€Šˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUTAUUUUUUUð aÃô$áÔ€áÔ€ÕŸ€±€±€˜–€¤Ë€±€Éj€½5€˜–€˜–€Œa€¤Ë€¤Ë€˜–€˜–€¤Ë€¤Ë€áÔ€çïÉj€½5€½5€±€±€½5€ÕŸ€ô$ ŽÃçï½5€ÕŸ€áÔ€áÔ€çïô$ô$çïçïYYáÔ€Éj€±€Éj€g€a¨a¨a¨UsUss÷€a¨= = = = $Ÿ0Ô= 0Ô= 0Ôj0Ôjj+Ä|+Ä| 5 5j0ÔI>g€g€a¨$Ÿ0Ô= s÷€a¨I>= $Ÿ$Ÿjj+Ä|+Ä+Ä|0Ôs÷€±€½5€s÷€€,€I>a¨g€˜–€€,€€,€¤Ë€€,€Usj0ÔI>jj 5$Ÿj$Ÿ= = a¨g€s÷€7777à BUFR&bÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌBUUUUU]kZÖµ­kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½ï½ï{Þ÷½ï{Þ÷½ï{Àж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUE@UUUUUUUUUUUUUUUUUUUUUð `˜–€s÷€˜–€ÕŸ€ô$$ø1-ÃçïáÔ€áÔ€çïçïô$ô$ÕŸ€¤Ë€g€I>= 0Ôj$Ÿ0Ô0Ô$Ÿ$Ÿj0Ô$Ÿ$Ÿ$Ÿ 5+Ä| 5 57 ‚±²}ú—‚7 ‚7 ƒ+Ä|jI>Éj€¤Ë€g€a¨s÷€Œa€s÷€s÷€˜–€½5€Éj€Us$Ÿ= = $Ÿj$Ÿ$Ÿ$Ÿ0ÔI>Œa€½5€çïÉj€Éj€½5€Éj€Éj€Éj€áÔ€ÕŸ€ÕŸ€±€€,€˜–€Œa€g€I> 5j$Ÿj 5$Ÿa¨Œa€½5€±€Œa€çïáÔ€ÕŸ€½5€Éj€˜–€s÷€a¨I>= $Ÿ 5$Ÿj$Ÿj0Ô€,€Éj€áÔ€áÔ€ÕŸ€ÕŸ€ÕŸ€çïáÔ€ô$$øý5€Éj€±€7777BUFR¶bÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýà\Ï…n6Ä´W0 ®`O€-ÆÀÛº«?nèÆŒ0!‘À6î€mÝÛº²Ð¡ Èà„€9ûÀs÷€ÉjzkÄé¬ Yø @@dµ@ÉjzkV~¡ ýà= €, ŽÐÈÖ )2àOX€¤Ë Žb“.é¬È¦°#`s÷ ޲dKT Yø!‘À= z ޲dÈw@6î€mÝÛº·tЬü L¸™p)2à„€= ·²Ä´È q°ã`3á@€,€çïÏÞc Æã`3á@Œa€·ô$«˜Æ q°\ÀO€ 5’|«˜|( ®`&% ^šÀ½5ÏÞ“.KTB@#`F0ÀŒa$ø“.“àdpO€!‘ÀC#€€,Y77775€BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUU@UUUUPUUPUUð aÃ$øçïáÔ€Éj€áÔ€ÕŸ€ÕŸ€çï$ø$øI—$øÃÃY ŽYô$ Žô$YÃ1-1-I—Œº€…I—1-UÌ€…ÃÃn6ÉÃâ-Õø½Ž¥$tPI—áÔ Ž ŽÉj=b=b$øáÔ€Œa€Œa€˜–€a¨a¨€,€˜–€¤Ë€Éj€¤Ë€g€€,€Œa€g€Us0Ô 5j7 €…‚±²|$Ÿ0Ôa¨˜–€Us€,€g€s÷€I>g€Œa€Éj€±€s÷€= 0Ô 5±²~7 ú—€…s€Œa€…‚7 €±²+Ä|0Ô= 5= s÷Yô$˜–€½5€€,€$Ÿs€Œa€O€Œa€Œaƒ+Ä|a¨1-UÌô$ÉjY$ø¤Ë€7777jBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€00 $’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*c\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUEUUUUTUUUUð `ô$$øçïÉj€Œa€Us$Ÿ$Ÿ$Ÿ 5j$Ÿj 5jI>Œa€±€±€˜–€½5€Éj€ô$ Ž$ø1-áÔ€çïÉj€Éj€˜–€s÷€= 0Ô= I>¤Ë€áÔ$øn6Œºn6€…bY$øbb€…˜ïŒºtPŒº˜ïŒº˜ïtP=b1-I— Ž=bUÌn6€…b=b$øÃ$øô$ÕŸ€ô$1-ô$Éj€˜–€Œa€a¨= +Ä| 5a¨0Ôj= I>¤Ë€áÔ€¤Ë€¤Ë€˜–€¤Ë€Œa€Œa€˜–€˜–€s÷€s÷€g€g€0Ô+Ä~7 ú—€…sss‚±²| 50Ôa¨Uss÷€€,€Œa€€,€±€€,€½5€±€˜–€¤Ë€s÷€s÷€I>7777jBUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€D0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@UTUUUPUUUUUUUUUUUUUUUUUUýà` 5~+k€€,€€,îb€€ú>tPîbƒ| 5$Ÿ= I>Us[€= I>}îb€ú>îbtP€€,€€,‚+k€$Ÿs÷€˜–€€,€€,€ÛºŒa€˜–€±€Éj€¤Ë€€,€[€= 5}îbîb€ú>‚+ktP€ú>tP‚¥}| 5[€€,€Us0Ô= = jj$Ÿ[€½5€˜–€˜–€Éj€çïÕŸ€s÷€g€€,€½5€Éj€Éj€Éj Ž=bUÌI—I—ÃÕŸ€±€ÕŸ$ø€…½ŽÕøÕø½ŽÕø±Y˜ï¥$=bÕŸ€Œa€˜–€¤Ë€ô$1-UÌbI—1- ŽÃbI—btPhUÌ=b=b$øÃÃ$ø$ø$ø Ž Ž$ø7777jBUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€\0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’[m¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc]N•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUEUUUUUUUUUTUUUUUUUUUUUUUUð ab˜ïtP=b=bY Ž=bÃI—ÃÉj€¤Ë€˜–€g€a¨s÷€UsI>UsI>+Ä|$ŸI>s÷€ô$áÔ€ô$Yçï½5Y€,€çïbÃô$±€g€I>= $Ÿj7 € 50Ô€,€g€I>$Ÿ0Ôs÷€˜–€¤Ë€½5€gÂÃ$øÃ¥$tPtPUÌáÔ€Us+Ä+Ä|I>¤Ë€½5Ã1-I—ñ€Œa€˜–€±€˜–YUÌÉÃ¥$˜ï¥$˜ïtP¥$n6I—Ã$ø$ø$ø€…‚=»1†ô}n6Yô$1-¥$‚²ÉÃâ-Õø€…€…ŒºUÌ=b1-$øÃI—˜ïÉÃâ-˜ï=bçïs÷€áÔ€ÕŸb7777jBUFRbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!²LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì‚UUUUUUUUUUUUUUUUUUUUUUUU]ï{Þ÷Îsœç9Îsœç9Îsœç8„!B„!B„!B!B„!B„!B„1ŒcÆ1ŒcÆ1ŒcÆ@‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýàaô}%Qô}IðV%²ô}t©‚ÕøÉÃhhô}ht‚½ç‚V%Œº¥$ŒºI—tP¥$½Ž‚ çht‚%QèHâ-˜ïŒºhI—Y¤Ë€ÕŸ$øh½Ž±YbUÌbh€…b€…½Ž½Ž¥$tP$øÃÃô$¤Ë€€,€[€I>[€¤Ë€Ûºçï$ø$ø$øÃ$ø=bI—bb$øô$Éj€çïUÌÃÛºs÷€I>$Ÿj 5$ŸI>g€¤Ë€Œa€Usg€˜–€¤Ë€€,€¤Ë€±€€,€˜–€¤Ë€±€¤Ë€ 5jj 5$ŸÉjYI—hÃÉj1-h€…ŒºŒº˜ï€…htP1-UÌ1-Ûº7777çïBUFR¶bÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð \çï²ÃP†  ®`/M`†GI—zĈ ®`Ð&% Us·UÌb³Åf )$X3ð] Æ]AŒºƒ ¸Ødp ÓX-PLK@ªæn6 õˆ¤O€3ðUs±tPƒ1ßÑB q°™pýà8u ^šÀ˜–€Ï…$ø$ø @ýàjÏÀ½5YÃPIð @“à 5jUsªæô$IðС O€„€0Ôa¨a¨$øÐ ®`ýàF0À˜–ò&\ ‰hÐ2Z zI—Ä¸Ø q°™p = †G€,€’|Ÿ Ið“à ®` dµ@˜–1-bZˆÈàýàF0À˜–èHˆ ë™p 5gàdµ@ÉjéôÖÄ´ÆÐ,@ ReÀ¤Ë€7777jBUFR¶bÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ(0I$’I$’I$¤’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN•µÀ …1Е-|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@#`\Ï…1†Ÿ¼?xdpð @@¤ËÏÞ>?xŒ0j#`@@s÷€Ï…ÏÞ>|(= ž±tP‚“.&\È » $Ÿ@@˜–[æƒJIc¾ ìtj,@ 3á@= a¨ô$Ÿ¼õˆ ëð @@±zkbZé¬ ‰h øP 9ûÀ˜–bbZ>|(dp 'À0ÔI>a¨ÃPIð¡ Ö 3á@C#€†G’|† Ð€Èà@@¤Ë·t @&\ ‰hÖ '¬@[€ž±=bÜlƦ°/M`ReÀ˜–Yn6Ül28 q°#`a¨$ø1†dÝÐ Ðã`!‘ÀC#€I>ÃPÜl|( 3á@mÝçïŸ nè?x »  I>­óA[æ€7777jBUFR¶bÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ<0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýà^“.õˆ L¸™p$Ÿ5gàLK@s÷€çïŸ Ül¸Ø~ð#`LK@½5bÄc Æ™p&% X€@Éjzk“.d –¨ #`3á@¤Ë1-UÌ«˜W0 ®`O€LK@Œa’Õ1†> L¸ &% ^šÀ½5bbZÄ´È øP#`9ûÀŒa€ªæ0Ô$øÐ 'À,@ X€@¤ËÃÏÞÄ´?x5gàdµAYIðôÖ&\ ð 9ûÀ˜–€çï²d?xŒ0#`^šÀÕŸ’ÕŸ¼KT Yø™p,@ €, ŽèHŸ¼ÝÐ ÓXÐã`*¹€$Ÿ0Ô€\À@@s÷€Ï…ÏÞ«˜|( 'Àã`9ûÀg€υŸ «˜“à 'ÀB@j[€7777jBUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀT0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUQUð `UsUsg€Œa€½5€áÔ€ô$ô$áÔ€çïÉj€±Ã=b Ž ŽÃ Žçïô$çïYÃô$ÕŸ€±€Éj€½5€ÕŸYÃI—=bÃáÔ€ÕŸY±€ô$1-UÌ$øYYô$Éj€ÕŸÃÕŸ€Éj€Éj€áÔ€ô$ Žô$$øYô$Yô$ Ž=bUÌ$ø$ø ŽÃÃý5€s÷€I>$Ÿ0ÔI>= Usa¨a¨g€a¨= = UsI>UsI>a¨UsI>$Ÿj+Ä| 5j 5+Ä~±²| 5jI>g€¤Ë€g€a¨g€Œa€g€s÷€Œa€½5€±€Œa€g€I>I>Us$Ÿ+Ä| 5±²~7 ‚7 €0Ôg€Œa€Œa€7777˜ïBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀh0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÐЦ5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUT@@UUUUUUUUUUUUUUUUUUUUUUUUð `˜–€a¨s÷€UsI>= UsUsUs 5+Ä|0Ô±²+Ä|Œa€Œa‚7 €Œa€a¨+Ä+Ä}€…‚±²~±²|$Ÿ±²+Ä|˜–€ô$ Ž˜ï¥$€…bUÌ=b1-=bçï¤Ë€ÕŸÃ ŽÕŸ€€,€a¨g€Usa¨½5UÌŒºÉØïtPI—n6I—ÕŸ€½5€Éj€€,€g€Œa€ÕŸ€áÔ$øô$ÃÕŸ€½5Y$øáÔ€± ŽŒº¥$˜ï˜ïn6ÃáÔ1-=bUÌ1-¤Ë€Us±€¤Ë€±€½5€¤Ë€¤Ë€½5€½5€çïáÔ€½5Ã$ø ŽUÌb=b ŽÕŸ€Œa€±€Éj€ÕŸ€½5€ÕŸ€çïáÔ€a¨$Ÿg€= I>g€= a¨g€±€7777˜ïBUFR&bÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÂUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_{ÞðB„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1ŒcB„!B„!B„!JP‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUAUUUUUUUUUUUUEUUUUUUUUUUUð `½5€±€Œa€s÷€Us+Ä+Ä| 5a¨ÕŸ€½5ñ€a¨I>$Ÿj0Ô= Usg€I>Uss÷ؖÀ…bbn6I—I—1-I—Œº¥$tP1-1-=bÕŸYô$½5€g€¤Ë€€,€˜–€€,€Usú—€…ú—ú—€…ƒ+Ä|€,$øÕŸ€j 5 5±²| 5$Ÿ 5j$ŸUsg€¤Ë€I>$Ÿ0ÔI>0Ô0Ô0Ôa¨áÔ Žs÷€ 5jj= $Ÿj= = = g€±€áÔ€áÔ€±€¤Ë€Us0Ô 5= áÔ1- ŽáÔ€= 5±²~±²}ú—s€…‚7 ‚7 €…‚7 ƒ+Ä~±²~±²}ú—ú—€ 5 57777BUFRöbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@""""#33333333334DDDDDDDDDDDEUUUUUUUUUUffffffffffffwwwwwwwwwwpŠ2ÇCŸÊt­®ˆd)Ž„©n|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUýàc~¥}|j[€s÷€Œa€ 5I>Œa€±€€,€˜–€Œa€I>I>g€[€Uss÷€€,€¤Ë€ÕŸ ŽçïÛº˜–€¤Ë€¤Ë€ÕŸYI—€…˜ï€…hbÀ,€I>Uss÷€Œa€ÕŸ€ô$bbh=bbYUÌô$ÃbtPâ-˜ïhÉØïÃI—UÌI—çïÉjtPÉØU̱€½5€±€Éj€ÕŸ€ÕŸ€Éj€Œa€s÷€s÷€[€g€€,€s÷€Us[€s÷€€,€˜–€Œa€Œa€€,€Œa€¤Ë€˜–€¤Ë€±€çïÕŸ Ž Žô$Éj€¤Ë€Œa€[€€,€[€I>g€±€½5€Éj€¤Ë€€,€s÷€[€I>Usg€= I>I>Œa€±€˜–€7777BUFRÆbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì40$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@,@ `C#€6î€j6î€C#€6î€6î€ 5C#€OX€C#€[€€,€OX€OX€OX€€,€g€[€€,€˜–€çïô$ô$ ŽY+¥$7G Ž Ž7G«?ÏÞ€…h7G[æ$øÃô$YY+Ã[æ[æY€,€OX€*¹€j„€[€ÃPà ŽÃô$ô$ô$ô$Ã[æhh+hܘï[ætPtPhhO±+tP˜ï·t¥$O±€˜–€ÃPô$ž±˜–€˜–€Ï…·YhC|€Ûº Ž[€C#€g€„€„€6î€[€·ô$·ªæž±ž±g€Œa€ô$·Ûº·s÷€˜–€ô$Ï…ªæg€C#€s÷€g€[€ªæ7777€¤BUFRÆbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌL@""""""DDDDDDUUUUUUUUUUUUffffffffffffwwwwwwwwwwpŠS RØ×>”é[\ÈS+k€" c¡*[¶>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ _ Åf ,\À'¬@= g€çïzkd ,™p'¬@ReÀº(A1-d¡ Œ0w@#`ReÀ½5‚²Ä´¡ È-piI Æ]AUÌ1->|(ÐÖ 3á@€,Y“.Ÿ¼|( øP#`F0ÀÉjb“.dp øP&% = €,€çïèHŸ¼d† €$Ÿ·ÄÝÐ L¸Œ0ð $Ÿs÷€çïŸ dÆ#`F0À½51-Ÿ zÄÐ q° 9ûÀÛºŸ ÐÝÐ øP #`3á@s÷€çïn6é¬ øP q°#`LK@½5ÏÞŸ¼c Œ0ð ýà-ÆÀÉj’Õd?x~ðýà)2àReÀ±1-1†KT øP/M`º(A1-7777€¤BUFR&bÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌUUUUUUU\ç:Öµ­kZÖµ­kZÖµ­k[Þ÷½ï{Þ÷½ï{Þ÷½ï|ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷ B‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUAUUUUUUUUUUUUUUUUUUTAð `½5€±Y˜–€½5€áÔYô$±€ÕŸ€˜–€¤Ë€±€ô$YÉj€Éj€±€¤Ë€½5€˜–€˜–€Éj ŽáÔ€¤Ë€˜–€˜–€s÷€g€I>= s÷ƒ+Ä~±²|Us= j+Ä+Ä~±²~7 ú—ú—ƒ+Ä~±²~7 ‚±²|Us 5Usjj$ŸUs˜–€½5€ç€˜–€s÷€€,€g€a¨½5€çï¤Ë€¤Ë€Œa€ÕŸbtPbI—1-$ø ŽçïáÔÃô$áÔ€¤Ë€g€s÷€˜–€€,€˜–€çïI—1-1-Y¤ËYg€g€s÷€g€I>I>Us€,€Éj€ÕŸ€ÕŸ€±€s÷€s÷€˜–€Œa€¤Ë€˜–€Éj€±€Œa€UsŒa€g€I> 5+Ä| 5+Ä+Ä| 57777BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RÜÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUT@UUð `I>Éj€çï½5€±€¤Ë€Œa€˜–€€,€¤Ë€±€±€s÷€s÷€I>= g€= = $Ÿ0Ô 5 5$Ÿ€,€áÔ€áÔ€Œa€±€Œa€s÷€g€s÷€˜–€Éj€±€Œa€±€Éj1-n6I—ô$ÕŸYg€¤Ë€½5Y½5€Éj€˜–€Éj€Œa€Œa€s÷€±€˜–€±€±€Œa€½5€˜–I—ÕŸ=b€…tPI—ÃÕŸ€áÔ€çï ޱ€Us$Ÿ$Ÿ0Ô$Ÿ$Ÿj0Ô$Ÿa¨€,Ã½Ž±YÕøŒº=b=báÔ€ô$ÕŸ€ÕŸ1-$ø= Œa€˜–€I>0Ô0Ô$Ÿj$ŸUss÷€g€s÷€= = j+Ä|7 ú—‚7 €jŒa€€,€0Ô$Ÿj 57777÷€BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUPUUUUUUUUUUUUUUUUUUUUð `jjj 5j$Ÿ= = +Ä|= jjI>ÕŸY˜–€s÷€a¨I>a¨UsUs$ŸI>I>$Ÿ0ÔI>g€g€g€$Ÿ±²+Ä|js÷€¤Ë€ÕŸ€¤Ë€Œa€I>= I>= = Us= I>0Ô= $Ÿa¨ 57 s‚7 €…ú—ƒ+Ä|Us˜–€½5€¤Ë€s÷€I>I>I>s÷€I>€,€ô$UsI>€,€a¨I>0Ô$ŸjI>j$Ÿ= €,€½5€Éj€¤Ë€ÕŸ€€,€s÷€ô$Éj€I>I>¤Ë€˜–€s÷€Œa€€,€g€I>I>I>Us$Ÿ+Ä|$Ÿ= 0Ô€,€Œa€a¨0ÔI>˜–€Œa€˜–€Éj€˜–€áÔ$øbŒºÉÀ7777÷€BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@00I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUTUUUUUUUUUUUUUð a¥$b=báÔ€ÕŸ€ÕŸ Ž¥$¥$€…ý5€½51-ÕŸ€€,€±€áÔ€Œa€½5€˜–€Éj€ô$s÷$ø=bY$ø ŽÃÃ=b$ø€,€a¨a¨$Ÿ0Ô$Ÿj$Ÿ0Ôj0Ô0ÔUs±€ÕŸ€½5€½5UÌI—Ãô$1-ŒºŒºÃŒa€a¨a¨g€a¨= a¨Us$Ÿjj0Ô±²|j 5$ŸUss÷€€,€áÔ€áÔ€½5€g€Œa€s÷€Us= I>0Ôj 5 5jj$Ÿ 5 5±²~7 €j±²|jjŒa€½5€g€g€˜–€Uss÷€a¨a¨I>g€½5€g€I>I>s÷€€,€˜–€€,€a¨s÷€a¨0Ôg€€,€Œa€7777÷€BUFRöbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@H@"""""33333333333DDDDDDDDDDDDUUUUUUUUUUUUffffffffffffwwwwwwpŠt%K”é[\„e:V×D2ÇBØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUEUUUUUUUUð `a¨s÷€s÷€Usa¨j$Ÿ= = $ŸjÕŸ€áÔ€Éj€¤ËYô$¤Ë€a¨$Ÿ 5jI>Œa€± ŽÉj€˜–€˜–€¤Ë€½5€½5€¤Ë€ÕŸ€¤Ë€ÕŸ$øb½ŽUÌçïs÷€I>a¨UsI>g€Éj€ô$ô$ÕŸ€Éj€½5€±€±€±€ÉjYÕŸ€ÕŸ€ô$áÔ€áÔ€€,€0Ôjj 5$ŸI>€,€¤Ë€s÷€a¨Œa€€,€g€˜–€±€ÕŸI—1-Éj€½5€½5€s÷€a¨0Ô+Ä| 5j0Ô½5Yô$áÔ€½5I—UÌI—$øô$áÔ ŽY ŽŒºtP ޽5€±€¤ËÃô$ô$½5€áÔ€çï¤Ë€s÷€a¨Us= 7777€ÉBUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@d0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUTUUUUUUUUUUQUUUUUUUUUUýà`[€= €,€g€Usg€€,€s÷€I>s÷€s÷€¤Ë€Œa€Œa€UsI>I>Usg€UsI>UsUs= Us[€[€[€= [€¤Ë€s÷€¤Ë€I>$ŸîbîbîbtPtP‚¥}|j$ŸI>= UsI>I>$Ÿ= I>= j1-ÉýŽbô$=bY½5€±€Ûº ŽÃô$ÕŸ€˜–€çïçïçïÕŸ€çï Žô$Éj€½5€ô$½5€€,€= j 5| 5$Ÿg€s÷€Œa€s÷€Usg€= s÷€€,€[€½5€€,€¤Ë€˜–€˜–€€,€g€Us= I>jjjjI>I>€,€g€˜–€Éj€ÕŸ€¤Ë€[€s÷€€,€Usg€I>I>7777¨BUFR&bÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌBUUUUUUUUUUUUUUUUUUUUUUUUU^÷¾÷½ï{Þ÷½ï{Þ÷½ï{ÀB„!B„!B„"„!B„!B„!CÆ1ŒcÆ1ŒcÆ1Œ„!@‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØçÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUUUUUUUUUUUTUUUUUUUUUUUUUUUUUð `g€Us 5+Ä~7 ‚7 € 5Us= Us= I>I>I>UsUss÷€g€= $Ÿ= I>½5Y$ø¤Ë€g€a¨I>I>= = = 0Ô$Ÿ0Ô0Ô$Ÿ0Ô$Ÿ0ÔI>0Ô0ÔI>±€çïáÔY$øÃÕŸ€Œa€Us0Ô= 0Ô 5±²| 5jj$Ÿj 5$Ÿ$Ÿa¨¤Ë€çïn6€…bÃYáÔ€Éj€ÕŸ€çï$øô$€,€±€Usa¨s÷€¤Ë€s÷€Éj€çï±€˜–€Œa€€,€Œa€g€I>= = 0Ô0Ôa¨˜–€±€Éj€½5€±€Éj€˜–€€,€±€Œa€±€±€˜–€ÕŸ½Ž€…n6 ޱ€¤Ë€˜–€g€g€˜–€7777BUFRÆbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@#``½5€ÃPÛº½5€ô$ô$ÛºÃP˜–€Œa€çïÃPÛºh¥$‚ çÏÞÏÞI—¤Ë€Ï…YtP€…$øçï½5€Œa€s÷€[€= C#€0ÔC#€OX€= C#€€,€˜–€Ï…$ø±€Ï…ÃPs÷€Œa€Ï…€…±YÏÞ=bÛºÛº$øh ŽÛºYI—¥$Ü=»1-Y€… Žg€s÷€[€ 50Ôs÷€Œa€g€s÷€€,€s÷€OX€€,€s÷€€,€s÷€€,€Œa€g€OX€˜–€ÛºÉÃŒº[æ[æYÏ…±€€,€OX€= C#€OX€C#€C#€0Ô= = $Ÿ0ÔC#€€,€ô$€,€g€s÷€OX€C#€jg€Œa€±€Œa€ô$ ŽÏ…ÃP˜–€˜–€7777=BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€(0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’Im¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+`C!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUQUUUUUUUUUUUýà`çïÛºÉj€ÛºÛºÛºô$ÕŸ€ÕŸY±€Éj€˜–€€,€€,€ŒaYYÛºÕŸ€Éj€çïÉj€ÛºÉj€Éj€¤Ë€±€˜–€±€Œa€s÷€[€= jI>Œa€¤Ë€±€½5€Éj€Œa€Œa€s÷€Œa€€,€˜–€ÛºŒa€Œa€¤Ë€ô$1-$øÃçïäˀçïYYI—ý5€Œa€Œa€Uss÷€€,€Œa€±€±€½5Yô$j$Ÿj| 5jI>ÉjÃÛº˜–€g€€,€g€s÷€[€Œa€s÷€I>jjI>€,€g€j€,€çï±€½5€ô$Y Žô$1-€,€[€j= $Ÿ0Ô$Ÿ= 0Ô$Ÿ0ÔUsI>I>7777j€BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€<0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ý¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUDUUUUUUUUUUUUUUUUUTUUUUQUð `UsŒa$øô$¤Ë€Usa¨I>= $Ÿj 5 5+Ä|+Ä+Ä| 5j0Ô= I>a¨a¨0Ôa¨s÷YÃ=bYI—tP$øô$½5€½5€áÔ€ô$Éj€Éj€ô$ô$ ŽáÔ€Éj€Œa€s÷€Usa¨= = I>s÷€˜–€ÕŸ€ÕŸ€Éj€˜–€€,€€,€€,€a¨g€Œa€Œa€s÷€$Ÿ0Ô$Ÿ$Ÿ±²| 5= I>¤Ë€ÕŸ€±€s÷€s÷€s÷€±€s÷€g€a¨a¨Us$Ÿ= 0Ô$Ÿ 5±²~±²~±²~±²+Ä+Ä|Us€,€Œa€s÷€˜–€¤Ë€½5€áÔ€ÕŸY ŽÃçïÉj€¤Ë€€,€s÷€±€= 5+Ä|$Ÿ˜–€±€¤Ë€7777j€BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€T0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUTUUUUUUUUUUUUUUUUð `˜–€½5€ô$çïáÔ€áÔ Ž1-à ŽÕŸ€±€áÔ€áÔYÃ=b=bÃYçïçïçïçïô$±€¤Ë€½5€˜–€±€¤Ë€g€g€s÷€s÷€±€áÔ€áÔ€ÕŸ ޽51-YÕŸ€¤Ë€Œa€˜–€= j$Ÿ0Ô0Ô$Ÿ= 0Ô0Ô= I>g€ 5 5 5 5+Ä|0Ôg€¤Ë€ô$ÉjY=b ŽYÉj Ž=b1-ô$Ã=bI—áÔ€±€Œa€$Ÿ½5€çïa¨UsI>¤Ë€áÔ€½5€Éj€áÔYô$çïYY½5€˜–€€,€¤Ë€ÕŸ€Œa€±€çï$øÉÀáÔ€€,€$Ÿj$Ÿg€Œa€Œa€±€¤Ë€ÕŸ€Éj€ô$Yô$ô$Y7777j€BUFR&bÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì‚UUUUUU\ç9ÎskZÖµ­kZÖµ­kZÖµ­ï{Þ÷½ï{Þ÷½ï{Þ÷¾sœç9Îsœç9Îsœç9Î÷½ï{Þ÷½ï{Þ÷½ï{ЋÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUTUUUUTð aÃÕŸ€ÕŸ€ÕŸ€±€áÔ€¤Ë€g€UsUs= j$Ÿa¨¤Ë€ÕŸ€½5€±€Œa€g€¤Ë€½5€ÕŸ Ž1-1-çï±1- Žçïçï±€ÕŸ€$Ÿj$ŸÉj€çïY$ø1- ŽçïÉj€Éj€½5€±€Éj€Éj€±€¤Ë€I>I>$Ÿj±²+Ä~±²~7 ‚7 ‚7 €$Ÿ= a¨g€a¨Usa¨€,€€,€g€Us= a¨g€= Us$Ÿa¨ÕŸ€Œa€s÷€g€= j±²~±²|+Ä|+Ä+Ä+Ä|jj$ŸI>Us0Ô$Ÿ7 ú—ss‚7 €0Ô= = $Ÿ 5j$Ÿs÷€g€s÷€a¨I> 5$Ÿa¨0Ô$Ÿ+Ä|7777BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠˆd)Ž…-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUPQUUUUUTUUUUUUPð aú—ƒ+Ä|0ÔI>Usa¨a¨s÷€Us€,€$Ÿ 5jj$ŸI>$Ÿ= a¨çïYÉj€€,€$Ÿa¨$ŸI>jI>I>a¨s÷€Œa€˜–€€,€s÷€g€I>$Ÿ= jj= = Usa¨a¨0Ô$Ÿj$ŸI>= Us0Ô0Ô$Ÿ+Ä~7 ƒ+Ä+Ä|j0Ôj 5+Ä|+Ä+Ä~±²}ú—‚7 ú—€j0Ôg€I>Œa€˜–€Œa€±€Œa€a¨a¨±€ÕŸ€ô$Éj€€,€€,€¤Ë€€,€€,€= I>s÷€0Ôj+Ä|j0Ô0Ô$ŸI>g€g€˜–€I>Usa¨I>= Us±€ÉjYÕŸ€±€a¨$Ÿ= I>0Ô0Ô7 ‚7 €7777BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ЗÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUEUUUUUUUUUUUUUUPUUUUð b±²~±²+Ä|+Ä|±²|jj0ÔjUs= j$ŸjI>±€ÕŸ€¤Ë€Œa€g€€,€g€a¨€,€Œa€¤Ë€Œa€Œa€¤Ë€±€˜–€¤Ë€€,€$Ÿj±²|a¨Œa€Éj€˜–€Œa€¤Ë€Œa€Œa€€,€UsUsUsg€g€Us$Ÿ 5+Ä~7 ‚7 ú—‚±²~7 ‚±²|$ŸUs€,€˜–€s÷€= = 0Ô= 0ÔUsUs€,€Us0Ô0ÔUsUss÷€a¨I>€,€s÷€Us= I>a¨a¨UsUsI>I>0Ô= = I>Us= I>s÷€˜–€I>0Ô+Ä+Ä| 5$Ÿ 5 5$Ÿ 5$Ÿ= I>g€¤Ë€±€€,€˜–€Éj€Éj€7777BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ00 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUU@@UUP@TPUUð `˜–€Œa€Œa€½5€€,€s÷€Œa€s÷€I>$Ÿjj7 ‚±²~±²+Ä| 5 5j$Ÿ$Ÿ$Ÿ$Ÿ= $Ÿ±²}€…€…€…€…€…‚7 ‚7 ƒ+Ä+Ä~7 ‚±²~7 ‚7 ‚±²+Ä|0Ô 5 5±²}ú—‚±²+Ä|$ŸUs˜–€€,€€,€€,€I>= $ŸI>I> 5+Ä}€…€…ú—‚7 ‚7 ‚7 €…‚7 ú—€…€…€…ú—‚±²|+Ä}ú—ú—ú—ú—‚7 ‚7 ú—ú—‚±²~±²}ú—€…‚7 €…‚7 ƒ+Ä|= g€s÷€€,€$Ÿ+Ä~7 ú—‚±²+Ä| 5+Ä}ú—ú—ú—€ 5j$Ÿjs÷€áÔ€áÔ€çï7777BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀH0I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠc¡*[èÊt­®ˆd)Ž„±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUUUUUUUUUUUU@UUUUUUUUUUUUð a$øUÌn6ÕŸ€ÕŸ€¤Ë€˜–€ÉjYa¨jj= $Ÿ+Ä~7 s€Œas€…ƒ+Ä|$Ÿ Žn6UÌ=báÔ€±€€,€¤Ë€ÕŸ€¤Ë€¤Ë€UsI>= Us¤Ë€¤Ë€¤Ë€€,€¤Ë€ô$$øUÌU̘ïI—ÕŸ€Éj€s÷€Œa€I>a¨€,€€,€¤Ë€áÔ€…ÕøYŒa€½5€a¨$Ÿ= g€Œa€˜–€Uss÷€g€ 5+Ä~±²+Ä+Ä|$Ÿ 5$Ÿs÷€ÕŸ$øÉj€±€a¨I>= gÂU̲ô}ÕøÃáÔ€Éj€¤Ë€±€½5€˜–€ÕŸ€Œa€˜–€±€áÔYÉj€¤Ë€UsI>s÷€ÉjbÃ½Ž‚ çIðÉÂ¥}tP€çï$ø=b=bÉj€7777BUFRÖbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!‚LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ\0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹)Ò¶¸!¦:¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðU@UUUUUUUUUUUUUUUUUUUUUUUUUUUUUð \ÃP† Ÿ¼€ @~¥àÀBÁ€…ÃÎ ,Ð øP#`9ûÀ½5bV~¬ü ÓX-P8u ^šÀ±ÃbZˆ L¸ýà@@a¨Ã1†c ?xŒ0ð ^šÀ¤Ë1-ÏÞd?x~ð2Z @@a¨’Õd O€&% I>†GÕŸ«?V~¬üÈàýà8u 3á@s÷€çïŸ &\Æ-P F0Àg€ÃP²Ÿ¼?xO€3á@I>’|ô$d ‰hŒ0 50ÔI>ÃPŸ èH @ ®`O€j$ŸYbZŸ¼ ‰h ®`j*¹€I>0Ôa¨Ið?x 5O€F0Àa¨a¨UÌIð€ 'À 5O€€,€çïÏÞ @“à 'À€ 57777bBUFR&bÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÂUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU^sœç8B„!B„!B„"„!B„!B„!CÆ1ŒcÆ1ŒcÆ1Œd!B„!B„!B…)JR”¥)JPŠ2ÇBX×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUTUUTUUð c+Ä|$Ÿ0Ô$Ÿ$Ÿ0Ôj$Ÿ0Ô$ŸUs= = UsŒa€I>$Ÿ$ŸjUsUss÷€±€˜–€s÷€g€UsI>I>= I>jI>s÷€Œa€s÷€a¨s÷€¤Ë€Éj€˜–€Œa€a¨€,€€,€g€s÷€g€a¨s÷€I>g€g€Œa€s÷€s÷€€,€˜–€Œa€g€a¨a¨ÕŸ1-çïÕŸ€Œa€Usa¨€,€Us0Ôs÷€ 5ss€Œa€O€O€Œas€Œa€Ossƒ+Ä~7 ‚7 ‚±²~7 ‚±²~7 ‚7 ú—‚7 ƒ+Ä|0Ôs÷€g€I>j 5 5+Ä~±²~±²| 5= I> 5j+Ä+Ä+Ä+Ä|$Ÿ€,YbI—±€Éjäˀ7777BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUTUUUUAUUUUð `Œa€g€s÷€˜–€g€a¨g€s÷€Usg€Us 5€…s€…€…‚7 €jUsI>I>I>= 0ÔI>I>Usa¨UsŒa€a¨g€Œa€¤Ë€¤Ë€¤Ë€¤Ë€¤Ë€g€€,€g€s÷€±€Éj€g€I>s÷€g€˜–€g€€,€¤Ë€˜–€±€½5€Éj€½5€s÷€ 5+Ä~±²~±²|+Ä|jI>g€˜–€±€Œa€g€g€s÷€s÷€€,€s÷€a¨g€I>I>j+Ä~±²|±²~7 €…€…‚7 ‚7 €j0Ô= 0ÔUs= g€g€Œa€Us$Ÿa¨Éj€I>€,€Œa€s÷€Usú—€Œa€O€O€O€Œa€…‚±²+Ä|ú—€…€Œa‚±²}€…ss‚7 ú—€ 577775BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì,0$’I$’I$’JI$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹[\ÈS RØ×>”é[\ÈS S\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUPUUUUUEUUUUAUUUUUUUUUUUUð `g€s÷€= ±²~7 ‚±²~7 €$Ÿ˜–€±€Éj€½5€¤Ë€g€I>s÷€s÷€UsçïY½5€0ÔI> 5j+Ä+Ä| 5$Ÿ$Ÿ0Ôs÷€˜–€Éj€áÔ€ÕŸ€±€¤Ë€€,€˜–€¤Ë€¤Ë€˜–€Éj€áÔ$øs÷€ 5+Ä| 5+Ä+Ä|Us½5€çïYô$ÕŸ€çï¤Ë€˜–€¤Ë€ÕŸ€½5€˜–€Œa€Œa€áÔ€¤Ë€g€ú—ƒ+Ä| 5ss‚7 €0ÔI>áÔ€a¨ÕŸ€Œa€0Ô0Ô 5j€,€½5=bîb±Y€Éj€½5$ø=b$øYYÉj ŽUÌUÌI—ç€s÷€€,€˜–€Éj€Éj€±€€,˜ï‚±²‚ↂt©‚%Qô}Œºñ€s÷Y±€77775BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌD0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUETUUUQUUUUUUUUUUUUUUUUUUUUUð `Œa€½5€€,€˜–€±€€,€0Ôg€0Ô= I>g€çïâ-½ŽŒºtPYÕŸ€Œa€+Ä| 5$ŸI> 5j+Ä| 5 5j 50Ôg€Œa$øn6½Žn6˜–€s÷‚±²|jj= a¨˜–à Žg€0Ôa¨ 5= 0Ô$øÕŸ€ô$UÌçï€,€a¨¤Ë€±€ÕŸ€€,b$ø=b=b1-ô}¥}‚¥}ÉÃn6½ŽÕø‚Ið±Y˜ïÃUÌb± ŽbI—áÔ€çïÉj€Éj€½5€¤Ë€Œa€g€s÷€Us˜–€a¨0Ô€,€= = Œa€˜–€ÕŸ$øbI— ŽçïÕŸ€ô$½5€˜–€Œa€€,€s÷€¤Ë€€,€a¨UsI>Us€,€˜–€77775BUFRæbÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌX0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUTUUUU@UUUUTUUUUUUUUð `±€½5€Œa€a¨a¨jú—ú—€Œa€…ú—‚7 ‚±²|±€˜–€áÔ€½5€¤Ë€±€ô$Œa€½5€Éj€€,€UsÉj€€,€s÷€= j+Ä~7 €…€+Ä~±²+Ä| 50Ô= = 0Ô$Ÿ0Ôa¨g€Œa€I>Éj€½5€˜–€±€˜–€€,€s÷€0Ô7 €…€Œa€O€O€Œa‚7 ‚7 €…ú—ú—‚7 ‚±²~±²| 5$Ÿ˜–€a¨€,€ô$çïÕŸ€¤Ë€€,€½5€Œa€Us= s÷€s÷€a¨$Ÿ$Ÿ±²}ú—ƒ+Ä+Ä| 50Ôg€Œa€Éj€ô$ô$ÕŸ€Éj€Éj€ÕŸ€Éj€±€˜–€s÷€€,€Œa€Œa€áÔ€çï Ž=bY±UÌ€…Œº€a¨ÕŸI—=bUs77775BUFR&bÿ« fÌ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌUUUUUUUU]ï{Þ÷½ï{Þ÷½ï{Þ÷¾sœç9Îsœç9Îsœç9Î÷½ï{Þ÷½ï{Þ÷½ï{ß{Þ÷½ï{Þ÷½ï{Þ÷½à„!BŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUTUUUUUUUUUUUUUUUUUUUýà`j= s÷€Éj€= g€՟€ÛºÕŸ€±€±€s÷€±€˜–€Ûº½5Ã$øÕŸYÛºÉj€¤Ë€I>}tPtP‚+k€$Ÿ½5€ÕŸ€Us[€Us[€€,€g€UsŒa€˜–€¤Ë€Œa€€,€= j~+k‚+ktP‚¥}|[€¤Ë€¤Ë€˜–€s÷€s÷€s÷€Œa€±€¤Ë€Éj€€,€s÷€g€՟€ÕŸ€Éj€±€¤Ë€˜–€[€Us$Ÿ= Us€,€¤Ë€[€[€g€€,€[€€,€±€¤Ë€˜–€±€ô$=bçïŒa€¤Ë€Œa€½5€±€€,€[€g€s÷€Usg€[€I>$Ÿ 5I>= $Ÿ$ŸI>g€g€ۺ$øh=b ޱ€g€0Ô[€I>s÷€˜–€¤Ë€7777BUFRæbÿ« fÌ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUU@UUU@UAU@UUUU@Tð `±€Œa€˜–€¤Ë€¤Ë€Éj€Éj€ÕŸ€ÕŸ€Éj€±€¤Ë€˜–€€,€UsUs 5ú—€Œas€…ú—€j$Ÿ 5$Ÿ$Ÿa¨˜–€s÷€Us= = 0Ôj 5±²|Œa€Œa€…ú—s€…‚7 €jUs€,€I>a¨I>UsI>$Ÿ 5$Ÿ0Ô0Ô= 5+Ä~7 €…s€Œa€Osú—€ 5g€¤Ë€€,€s÷€0Ôj+Ä+Ä|$Ÿ= $Ÿ 57 ú—ss€Œa€O€Œa€…€= ½5€˜–€½5€˜–€s÷€g€Usg€g€½5€Éj€Éj€áÔ ŽçïŒa€¤Ë€€,€ 5€…€…€…ú—‚±²|Œa€¤Ë€Œa€j0Ô+Ä~±²| 50ÔI>7777 BUFRbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÂLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðB„!B!„!B„!B„!B„!B„!B„!B„!B„!B„!B„ „!B„!B„!`±€±€çïhtPO±ÃO±ÃÉj€¤Ë€s÷ƒ“†ÿ“†üs÷€s÷‚bZbZtÿtü€,€˜–€Œa€Œa€˜–€€,€˜–€˜–Ys÷‚ŸctýèHèHn6ô$€,€Éj€ô$çïô$ۺυ½5€½5€¤Ë€Ï…çï½5€¤Ë€s÷€s÷€Œa€Œa€€,€˜–€€,€Œa€½5€Ï…=btPÉÃ¥$¥$tPI—hO±˜ï½ŽI—ÃO±I—[æ1-[ætPhI—=bà Ž$øO±I—I—1- ŽYçïô$ÃI— ŽÃçï½5€¤Ë€¤Ë€g‚bZtýèHŸcg€½5Y1-$øô$Yô$ÛºÛºÛºô$ Žô$çïÉj€ô$YÏ…½5€Œa€7777÷€BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@40I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUTAUUEUUUð c+Ä}ú—‚7 €¤Ë€çï½5€Éj€¤Ë€Œa€€,€a¨€,€s÷€Œa€¤Ë€±€ô$YÃYY Ž1-=b Žô$áÔ€½5€ÕŸ ŽŒºUÌÃô$çïô$áÔ€ô$±Y½Ž‚%QbZV%%Q çÕøn6$øYáÔ€½5€½5€ÉjYn6€…$øÉj€±€˜–€a¨Us¤Ë€˜–â-‚±²‚™H‚bZ=» çâ-tP=bYáÔÃn6îb‚½çUÌÉj€˜–€= Us$Ÿ$ŸI>Us€,€g€ 5 5 5 5±²|±²~±²|I>s÷€s÷€Us= 5 5+Ä| 5j$ŸI>0Ô$ŸI>I>j+Ä}ú—‚7 ƒ+Ä| 5I>= 57777ÛBUFRæbÿ« fÌ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@H0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUPUQU@UUUPUTUPDUUQUUUð `jj+Ä| 5$Ÿ$Ÿ+Ä~±²~7 ú—ú—ú—ú—ss‚±²|= Éj€€,€g€a¨j+Ä|j0Ôjj+Ä~±²+Ä+Ä~±²}s‚7 ƒ+Ä~7 ‚±²~±²+Ä|= = $Ÿjjj$Ÿ$Ÿ0Ô= $Ÿ0Ôjj+Ä~7 ‚±²~±²~±²~7 €j€,€¤Ë€s÷€= j0Ô+Ä~±²| 5a¨I>g€0ÔI>0Ôj7 €…‚7 ú—ú—ú—ƒ+Ä|0Ô= $Ÿ±²| 5±²~7 ú—‚±²+Ä| 5$Ÿj= = = 5j 5+Ä|€,€çïYYçï±€s÷€g€Œa€½5€g€€,€7777ÛBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì@\0I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹N•µÀ …1Ж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUPUUUUUUUUUUTUUUUUUUUUUð `g€Œa€áÔà Ž$øçï$øÃÉj€±€Œa€±Y€…±Y€çïáÔ€áÔY=b=bŒºI—1-Éj€¤Ë€€,€$Ÿ$Ÿ+Ä~±²~±²|±€ô$ÃçïÉj€ÕŸ€ÕŸ€ÕŸ€ÕŸ€çï Ž=bn6€…tPtPI—$ø Žô$YÉj€±€˜–€˜–€±€áÔ€ÕŸ€˜–€˜–€€,€Œa€€,€€,€˜–€˜–€˜–€½5€Œa€Œa€I>$Ÿjjú—‚7 €jg€¤Ë€ÕŸ€çïÉj€€,€€,€˜–€Œa€€,€s÷€˜–€˜–€s÷€Éj$ø½5€±€a¨0ÔUs 5$ŸI>g€Œa€s÷€s÷€UsUsUsa¨s÷€Œa€Œa€g€˜–€±€a¨= 0Ô±²}€…‚±²}ú—€7777ÛBUFR&bÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌBUUUUUUUUUUUUUUUUUUUU^sœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½èB„!B„!B„!„!B„!B„!BÆ1ŒcÆ0Š2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@UUUUUUUUUUUUUUUUUUUUUUUUTUð a€…s€Œa‚7 ‚±²~±²|+Ä+Ä~±²|UsUs€,€I> 5j$Ÿ+Ä+Ä}€…ú—‚7 € 5ÕŸ€±Ãô$ÕŸ€¤Ë€Œa€Œa€¤Ë€Œa€ÕŸ€ô$1-=bÃYçïçï½5€€,€g€€,€s÷€Œa€¤Ë€ÕŸ€ô$ÕŸ€Éj€±€€,€Œa€Œa€çïô$çïô$1-=bbUÌ$ø$øçïçïçï±€˜–€Œa€±¥$‚bZI—ÕŸ€¤Ë€áÔ€ô$áÔUÌŒº¥$±Y€…I—I— ŽáÔ€ÕŸ€¤Ë€˜–€Œa€Œa€½5€¤Ë€Éj€¤Ë€½5€a¨a¨g€s÷€Œa€s÷€Uss÷€s÷€s÷€áÔ€Éj€I>0Ô 5+Ä~±²|$Ÿs÷€±€áÔ€Éj€g€Us7777BUFR¶bÿ« fÌ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$¶Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBVƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð \ÃPô$èHÈ™p8u ^šÀ˜–I—ÄÄ´|(“àj 5ja¨d –¨¦° LK@ŒaÃ1†ˆ L¸™p/M`€,YÏÞÐ?x  &% 3á@I>çïŸ Ÿ¼  &% ReÀ˜–YbZc |( ®`ýàjÏÁYÏÞ‡Ré¬ ÓX /M`s÷€ÕŸ«?28ÆŒ0'¬@= jÏÀáÔ1-“.¬üÈà&% ReÀ’|$øIð28dpÈà„€5gàjÏÀ½5I—Äé¬ Yø:C#€z½5ÃÄdpO€:2Z pê@՟é‡R¤ –¨Œ0\Àj0ÔÃPôÖ?xýà= jÏÀ±I—V~?xB@ C#€’|ô$7777Ô€BUFR¶bÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€$0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]’Õc ?x³ð@@€,€ô$èHV~ÆÖ 6+0X€@dµAUÌè¡Ä´Æ™p1—PUs·€…‚衈 ëO€#`F0ÀŒa€áÔb‡Rdp '¬@ReÀ€,1-1†28 O€&% LK@†G Ž’ÕôÖ&\|(¡ B@j 5jÃP«˜ L¸¦°2Z ^šÀ¤ËbĈ -P&% F0Àa¨I>’|ÃPIð† B@$Ÿg€’|ÃP$ø @“à€j$Ÿa¨ÃP† “à 'À X€@˜–1-ÏÞc |( ®`ð *¹€I>zŸ &\ Yø-P)2àX€@çï«?%ª¤ ÓX /M`ReÀ±bV~d @“à 'Àj7777Ô€BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€<0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUAUUð `$ŸŒa€±€çïçï±€s÷€Œa€a¨€,€a¨Œa€±€½5€ô$ô$çïÉj€s÷€$Ÿ+Ä+Ä+Ä~7 € 50ÔÕŸYÕŸ€˜–€¤Ë€Œa€½5€˜–€¤Ë€±€ÕŸn6UÌ1-UÌÃY$ø ŽáÔ€ÕŸ€ÕŸ€áÔ€çï Žn6ŒºŒºtP1-ÕŸ€áÔ€ô$Y1-€…UÌ=b Žô$çïÉj€½5€$Ÿj$Ÿ 5s÷€ÕŸ€áÔ€Éj€çï¤Ë€Œa€¤Ë€çïÃI—ÕŸ€±€½5€½5€½5€¤Ë€j7 € 5 5 50ÔŒa€¤Ë€Œa€g€g€Usa¨Œa€Œa€±€¤Ë€ÕŸYáÔ€½5€Œa€€,€Us7 €…€I>g€g€s÷€Œa€Œa€Œa€Œa€Œa€7777÷€BUFRæbÿ« fÌ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€P0$’I$’I$’II$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶àŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜è[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUýà`Œa€s÷€[€¤Ë€s÷€g€Œa€[€= $Ÿj 5+k€ú>tPtPƒ|I>±€ô$ÛºÉj€Œa€Œa€˜–€±€Œa€Éj1-ŒºtPbUÌÃYçïÉj€Œa€s÷€g€Œa€½5€çïÕŸ€ÕŸ€ÕŸ€Éj€Éj€ô$ ŽY$ø$øô$çïYçï½5€s÷€±€Éj€ÛºÛºÕŸ€ÕŸ€±€¤Ë€±€Éj€çïô$1-UÌbtPbÉj€±€±€ÕŸ€ô$ô$YYÛºÉj€˜–€±€½5€½5€½5€±€çïÛºô$YI—hh¥$â-¥$UÌ€,€I>[€Us$Ÿ 5= ˜–€ô$ô$1-Y¤Ë€ÕŸY=bç€s÷€0ÔjUs0Ô0Ô7777÷€BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì€h0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUPUUUU@UUUEUUUUUUUUUUPUð `a¨Us˜–€s÷€Œa€Œa€Éj€±€s÷€a¨Uss÷€Usg€a¨çïÃáÔ ŽáÔ€½5€gƒ+Ä~7 ‚7 s€O€Œa€…‚±²+Ä|$Ÿ$Ÿj$Ÿj 50ÔI>0ÔUsÕŸ€s÷€0Ô±²}€…s€Œaƒ+Ä|I>g€g€€,€s÷€g€UsI>s÷€½5€€,€Us$Ÿjú—€ 5+Ä|O€O€Œa€Œaú—€s÷ ޽5€¤Ë€˜–€¤Ë€Œa€€,€˜–€ô$ô$ ŽI—$øô$áÔ€g€g€g€՟ ŽÉj€˜–€áÔYÃY½5€½5€Éj€±€çï ŽY1-=b=bÃçï¤Ë€Usa¨= +Ä+Ä|jUsÉj€ÕŸ€7777÷€BUFR&bÿ« fÌ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì‚UUUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷¼„!B„!B„!B!B„!B„!B„1ŒcÆ1ŒcÆ1ŒcÆB„!B„!@Š•-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUUUUTUUUUUPUUð `çïÉj€ô$±€áÔ€áÔ€ÕŸ€çïÕŸ€¤Ë€˜–€= j±²}ú—s€…s€Œas‚7 €UsáÔYô$ ޽5€s÷€˜–€½5€çïÃI— ŽÕŸ€g€= $Ÿ= 7 €…s€Œa€Œa‚7 €j= $Ÿ$Ÿ$Ÿ= = UsUss÷€˜–€s÷€˜–€= = s÷€0Ô+Ä~7 ƒ+Ä}ú—ss€Œa€…s‚7 ‚7 ‚7 ‚±²~±²+Ä+Ä| 5UsUsg€0Ô$Ÿ$ŸI>jú—s€O€…‚±²|$ŸI>Éj€¤Ë€a¨I>g€s÷€Œa€˜–€áÔ€½5€¤Ë€g€g€0Ô$Ÿ+Ä}ú—ú—s€Œa€O€Œa€…€ja¨g€a¨I>Uss÷€€,€çïÃ7777BUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðU@UUUDAUUUUUUUUUUUUUUUUUUUUUUUð aYç€I>+Ä~7 ú—€…€Œasú—ƒ+Ä|a¨˜–€a¨Us0Ô0Ôa¨a¨g€Éj€ÕŸ€¤Ë€±€a¨¤Ë€= +Ä| 5€…€+Ä}ú—€$Ÿ€,1-UÌ=báÔ€Éj€±€˜–€áÔ$ø=b1-Ã$øY ŽÃYô$áÔ€ô$Éj€Éj€¤Ë€½5€áÔ$ø ŽÉj€ÕŸ€¤Ë€ÕŸYY ŽI—I—Ã$ø1- ŽáÔ€çïs÷€s÷€€,€= g€˜–€Œa€s÷€¤Ë€Œa€g€g€g€½5€çï Ž$ø=btPI—¥$±Yb=bÃYÉj€Éj€ÕŸ€Éj€Éj€½5€¤Ë€ÕŸ€áÔ€Éj€áÔ€ÕŸ$øtPn6˜ïUÌÃ$ø ŽYô$ô$7777ŸBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ,0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTUUUUUUUUUUUUUUUUUUUUUUUUUð `ô$ô$çïYYÃY=bbI—ÕŸ Ž$ø$ø1-I—$øÃ Žçï½5€Us±²~7 ú—s€…€jUsŒa€€,€Œa€€,€s÷€s÷€€,€s÷€Éj Ž ŽáÔ€±1-$øáÔ€€,€0ÔjUs˜–€ÉjÃÃ=bUÌYÃ$ø=bn6Œº¥$¥$˜ï˜ïÕø½Ž±Yb1-1-=b=bI—$øI—$ø=bÃ$ø Ž$øI—UÌ=b$ø1-Yô$Yçïô$çïáÔ€áÔ€áÔ€ô$YYY$øçïY=bbUÌ€…€…¥$ÉñY¥$Œº˜ïŒºtPn6I—=b$ø ŽÃ ŽÃ Ž Ž7777ŸBUFRæbÿ« fÌ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀ@0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¦5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUTUUUUTUUUUð `çï Žô$ô$ô$áÔYô$ô$Éj€ô$ÕŸ€áÔ€ÕŸ€±€Œa€€,€a¨0Ô0Ô= jg€g€g€Usa¨Œa€¤Ë€˜–€€,€g€g€a¨€,€Œa€˜–€g€= 0Ô+Ä| 50Ô˜–$øbUÌI—I—1-1-1-1-UÌbtPâ-Œº˜ï€…ÃYYô$çï½5€½5 Žç€€,€$Ÿa¨UsŒa€Éj$ø$øÃÕŸ€½5€¤Ë€Œa€Us 5±²~±²+Ä| 5j$Ÿa¨ÕŸÃô$çïçïçïô$ Ž ŽçïáÔ€ô$Éj€¤Ë€a¨$Ÿ 5+Ä| 5Us½5€Éj€ÕŸ€ô$1-$øYô$1- ŽUÌŒº±Yn67777ŸBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÀT0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUPUUUUUUð aUÌbUÌb=b ŽÃäˀg€€,€½5YçïçïYÉj€áÔ€áÔ ŽÃ=b=bà Ž$øçïáÔ€½5€Œa€s÷€€,€€,€˜–€˜–€±€±€Éj€Éj€±€¤Ë€¤Ë€s÷€Œa€s÷€ÕŸYçï¤Ë€ÕŸ€€,€j$Ÿ$Ÿ$Ÿ$Ÿ$Ÿ 5˜–€¤Ë€¤Ë€½5€ÕŸ€ÕŸ€ÕŸ€˜–€I>I>a¨I>Uss÷€Éj€€,€s÷€s÷€= I>$ŸI>½5€˜–€Éj ŽÃ Ž ŽÕŸ€ÕŸ€áÔ€áÔ€ÕŸ€½5€˜–€Us0Ô$Ÿ 50Ô+Ä}ú—€j 50ÔŒa€ô$à ŽYçïY±€ô$I—n6bn6=b1-ÃÃÃÃÃô$7777ŸBUFR&bÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌÂUUUUUUUU]kZÖµ­kZÖµ­kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½èB„!BŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUAUUUUAUUUUUUUU@Uð `Éj€Éj€±€çïY=b1-ÃáÔ€½5€˜–€ô$=b1-$øÃYÃ$ø1-Yà Žô$áÔ€ÕŸ€½5€áÔI—ŒºÕøîbbUÌb½Žô} çÕøUÌ ŽYáÔ€ÕŸ€¤Ë€0Ô$Ÿ 5 5ú—‚±²|a¨ÉjYY±€áÔYô$¤Ë€±€Éj ŽÕŸ€˜–€€,€= s÷€+Ä~±²|Œa€O€Œaú—ƒ+Ä|Usg€s÷€€,€€,€Œa€ÕŸ€ÕŸ1-$ø$ø1-=bÃ=bYYô$ô$Œa€a¨0ÔI>= I>UsI>a¨s÷€a¨$Ÿ0Ô$Ÿ= I>j+Ä~7 €…€…‚7 ssss€…‚7 €a¨½5€±€Œa€7777BUFRæbÿ« fÌ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì0’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBVƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUU@UUUUUUUUUUUUUUUUUUUUUð `€,€€,€€,€½5€Éj€áÔYÃb=bô$çïáÔ€a¨g€Uss€Os€jUs€,€s÷€I>= Usg€s÷€½5€Us$Ÿ±²|Œas€Os€…€Œaú—€= €,€¤ËYçïô$˜–€€,€€,€Éj=bUÌ=bI—$øô$ ŽÃ ŽÉj€ÕŸ€ÕŸ€±€±€˜–€±€ÉjÃ$øtPîb‚V%ↂ¥}‚Iðô}Õøâ-¥$â-‚t©‚ çU̽5€Éj€Éj€½5€Éj€½5€áÔYÃ$øYI—UÌI—ÃÃÃ=bÃô$çïáÔ€ÕŸ€ÕŸ€Éj€ÕŸ€Éj€Éj€½5€½5€½5€ÕŸ€ÕŸ€áÔ ŽáÔ$ø1-˜ï±YU̱YUÌÃ7777ŸBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUTUUUUUUUUUð a$øbbñ€˜–€s÷€€,€€,€€,€s÷€g€a¨= g€a¨s÷€€,€Œa€Œa€Œa€Œa€Œa€½5€ÕŸ€Éj€ÕŸ€ÕŸ€áÔYçïô$ô$çïÉj€Éj€±€½5€½5€ÕŸ€ÕŸ€çïçïçïçïô$ Ž1-I—=b1-ÕŸ€±€±€˜–€Œa€Éj€çïÉj€¤Ë€a¨UsI>I>= a¨a¨g€g€€,€€,€g€I>$Ÿ 5 5j 5+Ä+Ä|= Uss÷€s÷€s÷€g€€,€Usa¨a¨a¨g€g€a¨Usg€a¨Us$Ÿ±²|7 s€Os€$ŸUsa¨a¨I>I>Uss÷€¤Ë€½5€áÔ€Éj€Éj€½5€½5€Éj€±€½5€½5€±€Usa¨7777ŸBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì40$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I%¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƾ”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUTUUUUUUUUUUUUUUUUUUUð `$Ÿ$ŸUs¤Ë€ô$Yô$çïçïÉj€çï=bUÌ=b1-=b1-1-UÌI—=bUÌô$çïáÔ€áÔ Ž Ž ŽYYYô$çïáÔYáÔ€áÔ€¤Ë€€,€½5€€,€0Ôj0Ô0Ô0Ô+Ä}€…€Œa€…€±€Usg€˜–€¤Ë€¤Ë€±Y1- ŽYà ŽçïáÔ€Éj€±€½5€a¨g€˜–€g€€,€˜–ÃçïçïÉj€ÕŸ€Éj€áÔ€½5€ÕŸ€áÔ€áÔ€çïYYçï½5€çï½5€˜–€±€±€ÕŸ Ž$ø$øÃáÔ€Éj€ÕŸ€áÔ€±€¤Ë€±€¤Ë€±€±€±€±€Éj€½5€½5€˜–€€,€s÷€a¨s÷€Œa€˜–€¤Ë€±€½5€Éj€7777ŸBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌH0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUPUUUUTUUUUUUUUð `áÔ ŽYYÕŸ€áÔ€ÕŸ€½5€Éj€¤Ë€¤Ë€˜–€Œa€Œa€€,€€,€€,€¤Ë€ÕŸ€áÔ€¤Ë€g€Uss÷€g€s÷€€,€Œa€˜–€¤Ë€˜–€˜–€€,€s÷€g€€,€˜–€€,€€,€s÷€€,€Œa€¤Ë€˜–€Œa€g€a¨g€Usg€g€a¨a¨a¨I>0Ô$Ÿ 5+Ä}€…s€Œas‚±²| 5Us±€½5€±€Us+Ä| 5ja¨g€g€a¨g€a¨I>0Ô$Ÿjj+Ä+Ä|jI>0ÔI>g€s÷€s÷€a¨a¨s÷€Œa€g€s÷€g€Uss÷€Usj7 ‚±²~±²+Ä|j= UsŒa ŽçïÕŸ€½5€€,€s÷€s÷€¤Ë€¤Ë€s÷€˜–€áÔ€7777ŸBUFRæbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ì\0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUUUUUUUUUPUUUUUUUUUUUUUUUUUUð `ÕŸ€˜–€7 ‚7 ú—ú—€Œa‚±²| 5j= I>= $Ÿj 5 5I>s÷€½5€½5€½5€¤Ë€I>= g€Us$Ÿa¨˜–€I>= €,€¤Ë€¤Ë€Œa€¤Ë€¤Ë€Œa€Us= = g€˜–€s÷€g€$Ÿ˜–€½5€áÔ€±€½5€gÂú—‚±²|g€¤Ë€çïáÔ€çïs÷€$ŸUsg€Œa€±€Éj€ÕŸ€½5€Éj€½5€±€Éj€½5€¤Ë€g€s÷€g€Usa¨s÷€€,€˜–€±€½5YYÃ Ž Ž=bI—=b1-YÃ$øÃYYáÔ€Éj€g€I>a¨€,€Us€,€€,€g€g€Œa€˜–€± ŽYô$ÕŸ€çïçïáÔ€ÕŸ€±€Éj€½5€±€½5€7777ŸBUFRfbÿ« fÌ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÌUUUUUUUUUUUUUUTD»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»^sœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷¾÷½ï{Þ÷½ï{Þ÷½ïx„!B„!B„!B!B„!B„ ŠS RØ×>”é[\ÈS RØ×>”é[\" c¡*[çÂ2+kˆd)Ž„©lkŸÊt­®ˆd)Ž„©sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUAUUUUPUUUUUPUUUUUUUUUUUUUð `½5€ÕŸ€áÔ€ô$áÔ€áÔ€çïÕŸ Ž ŽÃ$ø Žô$ÕŸ€Éj€½5€¤Ë€Œa€I> 5±²~7 €jŒa€ô$1-YYÉj€¤Ë€½5€Éj€Éj€áÔ€ÕŸ€½5€s÷€I>Us0Ô+Ä~±²~±²}ú—€…ú—€0ÔÕŸbY ޽5€g€˜–€±€$Ÿg€½5€çïÃÉj€Œa€jI>¤Ë€g€ 5+Ä}ú—‚7 € 5= = I>I>I>€,€€,€Œa€±€Œa€0Ô±€½5€ÕŸ=b1-I—$ø Ž ŽhhI—[æ[æ=bI—UÌh€…€…€…I—Ûº½5€ÕŸ€ÛºÛºçï¤Ë€±€ÕŸ€ô$ô$$øUÌ1-I—Ã1-Yô$Y±€7777BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@ 0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …2¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@UUUTUUUUUUUUUPUUUUDUUUUPð `ç€g€Us0Ô$ŸI>j 57 €…€Œa€…‚±²|$Ÿ$ŸI>Us[€Us= €,€s÷€s÷€g€I>Us0Ô$Ÿ= 5+Ä~7 ú—€…sƒ+Ä|Us$Ÿ$ŸI>I>[€g€s÷€€,€±€½5€Éj€½5 ŽÛº½5€ÕŸ€¤Ë€€,€€,€Œa€€,€˜–€½5€ô$$ø=bÃ=b1-ÃI—tP[æUÌçï¤Ë€˜–€¤Ë€I>= +Ä~±²~±²|jI>Œa€¤Ë€ÛºÕŸ€çï ŽÃ$øô$±YçïY¤Ë ŽÕŸƒ+Ä| 5±²+Ä|j$Ÿ¤Ë€Éj€Éj€Éj€½5€ÛºÉj€±€˜–€ÕŸY$øÃô$ÕŸ€ÛºŒa€7 ‚7 €7777=bBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@$0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð a€…€…ú—€0Ԥˀ՟€¤Ë€¤Ë€Ûº€,€s÷€¤Ë€¤Ë€Éj€ÕŸ€ÛºY$øYÉj€±€±€±€±€±€ÕŸ€ÛºÛº±€çïçïg€€,€[€g€˜–€½5€½5€Éj€½5€Éj€ÕŸ€ÕŸ€ÛºçïÛºÛºÕŸ€Éj€±€±€±€¤Ë€½5€½5€Éj€Ûºô$YYÃÃYçïÕŸ€Éj€±€Œa€˜–€s÷€g€[€[€I>$ŸI>[€Us[€g€s÷€g€g€Œa€s÷€Œa€g€Œa€[€Us[€I>= $Ÿ 5±²~7 ‚7 € 5$Ÿ[€€,€s÷€Œa€¤Ë€±€Éj Ž[æ=bYÃ1-Y Ž$ø Žô$ÛºY½5€ÉjY1-I—hŒº€7777=bBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@80’I$’I$’I)$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠ¥±®„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¸FS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUTUUUU a˜ïŒº½Ž±YŒº½Ž¥$‚²ô}±Y¥$±Y¥$€…€…[æ[æ[æ[æC|€…‚²%Qht‚P [æÃ ŽY$øô$çï ŽÃ$øÃ Ž Ž ŽÛºÏ…Ï…YY1-1-€…hO±‚Ið‚‚1†ÜÉÃ¥$tP[æC|$øÃ Žçïçïçïô$ÛºçïçïÛºÃP Žô$Y1-1-1-Ã1- Žô$½5€s÷€s÷€0Ô 50Ô0ÔOX€ÛºYçïÛºÃPÃP¤Ë€Œa€˜–€çï½5€g€= = 0Ô 5 5™H}hhƒZ|$Ÿj$Ÿj$ŸC#€C#€C#€= s÷€s÷€g€[€OX€€,€s÷€0Ô7777=bBUFR¶bÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@L0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð \I>$øÃP ®`O€3á@ô$·Íoš L¸™p+|ÐLK@ŒaI—·Í&\ ß4\À&% I>€,€ô$ÏÞnèé¬ L¸¦°2Z jÏÁÃzÄ“à 'À~ð ®`ã`9ûÀ[€çï1†c L¸™p 9ûÀ€,bnè?xB@ýà= zY1†dÈB@#`C#€€,$ø1†d?x Yøw@5gàs÷YÏÞnèÝÐ ÓX-P/M`X€@Ûºc Æ$ŸOX€˜–=b1†c ëÐýà@@s÷ Ž·tôÖ¡ » -P6î€s÷€çïÏÞÄ´dp~ð!‘À= †GY nÈO€.Š`!`˜–I—·Í“àdp~ðw@9ûÀs÷Y7777$BUFR&bÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍBUUUUUUUUUU\cÆ1ŒcÆ1Œg9Îsœç9Îsœç9ÎsœëZÖµ­kZÖµ­kZÖµ­o{Þ÷½ï~÷½ï{ÞðB„!B„!BŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUPUUUUUUUUUð a=bèH¥}‚â†ÉÃ1-çïY ŽUÌ€…tP[ætPtPtP¥$tP=b1-[æh[ætP€…Õø‚Iðht1-1-UÌ Ž ŽÃ¥$¥$ÉÂIð ç±Yh±Y½Ž=bô$$øtP˜ïâ-‚² ç²½ŽŒºh˜ïh1-çï½5€ÕŸ€çïÕŸ€ÕŸ€= Uss÷€€,€¤Ë€ÛºÃ½Ž‚™Hƒ @g€˜–€Éj€Éj€Éj€ÕŸ€Éj€Éj€Éj€g€j+Ä}ú—ú—‚7 ƒ+Ä|jUs€,€¤Ë€±€±€Éj€çïô$çïYçïÛº½5€Éj€çïÛºÕŸ€ÕŸ€¤Ë€±€±€±€Éj€±€€,€Œa€¤Ë€¤Ë€s÷€Œa€g€€,€¤Ë€çïÃ7777Ÿ€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUDUUUUUð a1-I—=b$øô$Ûºô$ô$Ûºô$YÃUÌ¥$€…€çïÛºçïÕŸ€çïY$ø$øY½5€˜–€Œa€Œa€s÷€0Ôjj0Ô$Ÿ= s÷€¤Ë€˜–€¤Ë€€,€€,€€,€±€çï ŽI—[æÃÃÃô$¤Ë€ÕŸ€ô$Éj€çïÛºÛº½5 Ž1-Ã1-[æYÕŸ€½5€Ûº=b€…htPhUÌUÌYÕŸ€±€Œa€= = jŒa€ô$ô$Ûº˜–€Œa€s÷€s÷€˜–€çï ŽÛº€,€Œa€¤Ë€€,€I>0Ô+Ä|+Ä+Ä| 5jg€s÷€½5$øÃÃô$ÕŸ€çïÕŸ1-¥$ÉÃÉÃ½Ž½Ž¥$tP€…€…€…€7777Ÿ€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€ 0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUPUUUTUUUUUUTUUUUPUð a1- Žô$ÛºÛºYÛºÕŸ€ç€€,€UsŒa€çï=b1-ô$ô$Ûº¤Ë€Œa€€,€s÷€I>$Ÿ 5ú—‚±²+Ä|+Ä|$ŸI>¤Ë€s÷€[€€,€¤Ë€Éj€±€g€g€= 5 57 ƒ+Ä~±²+Ä| 5[€˜–€Œa€¤Ë€g€$ŸjjI>I>Œa€$Ÿ+Ä~±²| 5+Ä+Ä~±²~7 €…‚7 €€,€ÉjYçï¤Ë€Éj€ÛºI—ÃY½5€ÛºY½5€[€$Ÿ+Ä~7 ‚7 ‚7 ƒ+Ä|jg€±€Ûº±€±€½5€±€±€ÕŸ€±€ÛºÕŸ€˜–€g€Œa€j 5+Ä~7 ƒ+Ä|$Ÿ±²}ú—‚±²|= Us€,€[€[€= = 7777Ÿ€BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€40$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUDUUUUUUUUUPEUUUUð `0Ô0ÔI>Us¤Ë€s÷€s÷€[€Œa€çïÕŸ€s÷€UsUss÷€ÕŸY1-€…tP¥$Œº[æhI—I—h½Ž½ŽÕø€…I—1-ô$½5€Éj ŽÛº€,€$ŸjI>g€¤Ë€½5€˜–€çï±€s÷€˜–€±1-[æÕøtPYY±€€,€€,€s÷€0Ôj 5+Ä|±²|j0Ô$Ÿ= $Ÿ0ÔI>I>I>[€s÷€g€I>0ÔI>jI>= [€s÷€Us¤Ë1-[æ ŽÛºô$YçïÕŸ€Éj€½5€Éj€˜–€g€UsI>$Ÿ+Ä~7 €0Ô±²|jjI>Us˜–€¤Ë€s÷€g€g€I>j$Ÿ[€s÷€¤Ë€[€Œa€[€7777Ÿ€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€H0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTUUUPUUUUUUUUUUPUUUPð `€,€s÷€g€€,€= $Ÿ$Ÿ= g€Œa€çïô$Ûº±€˜–€¤Ë€˜–€s÷€€,€€,€Œa€= +Ä~±²}ú—‚7 €…€…€…€…‚±²~±²| 5±€ç€s÷€= UsI>I>Usg€Œa€g€I>0Ô$Ÿ 5+Ä~±²~7 €…€…€…‚7 €jUs±€Éj€UsUs€,€$Ÿg€€,€Éj ŽÛºŒºhY±€˜–€UsUs$Ÿ[€I>I>Us[€g€Us€,€s÷€€,€€,€s÷€€,€€,€±€ÕŸ€˜–€s÷€€,€UsUs0Ôj 5+Ä~±²+Ä|j$Ÿj 5 5 50Ô0Ô0ÔUsI>= 0Ô$Ÿjj+Ä}€…ú—ú—ú—‚7 €7777Ÿ€BUFR&bÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í‚UUU[Þ÷½ï{Þ÷½ï{ÞøÆ1ŒcÆ1ŒcÆ1ŒcÎsœç9Îsœç9ÎsœçZÖµ­kZÖµ­kZÖµ­k{Þ÷½ï{Þ÷½ï{Þ÷½ìŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×Â2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUTUUUPUUUUUUUUUUUUUð c+Ä|0Ô€,€ÛºŒa€¤Ë€s÷€[€Us[€Œa€çïô$½5€$Ÿ 5+Ä|±²~7 ú—€…ssú—ƒ+Ä|Us€,€= = $Ÿj 50ÔUs±Ã€…€Éj€g€s÷€= 57 ú—ú—€…ú—‚±²|0Ô±€çïg€[€= 0ÔUs½5€ÕŸ€±€s÷€€,€g€Us[€$Ÿ+Ä+Ä+Ä~±²|jI>¤Ë¥$h=b[æ$ø ޽5€ô$=b1-tPUÌYÕŸ€€,€0ÔI>$Ÿ±²~7 ‚7 € 5s÷€ÕŸ€ÕŸ€ÕŸ€ô$Éj€¤Ë€g€¤Ë€±€çïUÌô$$ø[æh ŽI—±€Œa€Œa€˜–€UsUs±€Éj€½5€¤Ë€Œa€[€[€Us7777Ÿ€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUUUUUUUUUUUUUUð `UsUsUsŒa€Éj€€,€[€0Ô= $Ÿ±²~7 ú—sss€…ƒ+Ä~±²+Ä+Ä~±²|+Ä~7 ƒ+Ä| 5$Ÿs÷€€,€s÷€€,$ø ŽÃŒa€Œa€Œa€Œa€˜–=b±Yâ-h=b=b1-à Ž$øI—$ø1-Œº=bÃÉj€ô$ô$Éj€s÷€˜–€[€Usg€¤Ë€ÕŸ€çïçïYô$Éj€ÛºYçïÛºÕŸ€Éj€Éj€Éj€ÛºÕŸ€Éj€çïÛºÛºÛº½5€˜–€ÛºYÉj€˜–€Œa€±€ÛºÕŸ€ÕŸ=bI—1-Éj€€,€[€çïY¤Ë€€,€s÷€€,€¤Ë€ÕŸUÌ%Q1†[æ€g€±€[€€,€s÷€[€g€ô$ô$ÛºŒa€s÷€7777øBUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶Û¶Û`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUQUUUUUUUUUUUUVUUUUUð `¤ËY1-hUÌÛºs÷€Œa€ÕŸ1-hUÌUÌ1-Yô$ô$çïçïô$ÕŸ€¤Ë€Éj€ÕŸ€ÕŸ€½5€½5€˜–€±€g€g€˜–€€,€I>€,€¤Ë€€,€s÷€j0Ô 5= €,€€,€g€I>$Ÿj 5$Ÿj±²|0ÔI>0ÔI>[€= Us0ÔI>Uss÷€Ûº ŽY Ž$øUÌhtP€…[æI—Ø–€ÛºtP˜ï[æ=b[æ[ætP€…½Ž±Y‚ ç€Þ‚½ç‚ↂ™H‚ht‚%Q½Ž€…I—1-UÌ1-¥$‚€ÞƒhÍ€+UÂhtPÉÂht‚ôÖÊ‚è¡=»˜ï€…UÌh=bUÌUÌ€…¥$½Ž±Y€7777øBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ00I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUEUUUUUUUUUU@UUUUUð aèHÕøÉÃô}±YY¤Ë€Éj€ÉjYYhŒºŒºtP±Y€…=bÃÉj€€,€Usg€ÉjÃ=bçïô$˜–€g€€,€g€˜–€½5€½5€¤Ë€½5€˜–€˜–€±€g€0Ôj 5+Ä|€,€Éj$øÛºÕŸ€½5Y½5€˜–€Éj$øçïÕŸ$øô$YÃñ€Œa€ 57 ‚7 ú—€ 5$Ÿ0Ô= 0Ô0Ô[€s÷€s÷€= [€¤Ë€Ûº˜–€¤Ë€€,€[€UsUs±€[€ 5ú—ƒ+Ä+Ä}ú—€…ú—‚±²~±²+Ä+Ä~±²+Ä|0Ô[€[€UsUs$Ÿ$Ÿjj 5I>g€±€ÕŸÃÛºÛºçïÕŸ€ÕŸ€ÕŸ€7777øBUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀD0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUTUUUUUUUUUUUUUUUUUUUUUýà`[€¤Ë€ô$ÉjÃ$øÏ…çïçï½5€= j~¥}|[€€,€Ï…Ûº˜–€€,€g€j0ÔOX€€,€s÷€I>$Ÿjîbîb€€,îb€€,€€tP€j€,€˜–€OX€[€€,€€,€€,€¤Ë€Œa€ô$Éj€Éj€¤Ë€[€s÷€±€= I>[€= $Ÿj= ¤Ë€Éj€Ûº±€¤Ë€€,€€,€€,€¤Ë€€,€¤Ë€çïçïÃÏ…Ï…0Ô|0Ô˜–€€,€$ŸOX€Œa€ô$ô$½5€½5€OX€I>g€s÷€½5€ô$Ø–€Ûºô$Ï…= = OX€¤Ë€ÛºÛº½5€½5€çïY1-Ï…˜–€= 0Ô[€[€€,€g€Œa€ÛºYô$Ûº¤Ë€[€7777øBUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀX0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶í¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUPUð `[€I>Usj±²~7 ú—‚±²|j$ŸI>[€s÷€UsI>[€±€±€±€Éj€Éj€Éj€ÕŸ€ÕŸ€ÕŸ€€,€€,€±=b1-$ø=bI—I—I—I—Ã1-=b[æ[æI—[ætP ŽçïÛºŒa€Œa€Œa€¤Ë€±€Œa€ô$I—€…[æ[æ$øçïô$çïY[挺[æ[æI—$øY€,€= I>0Ô$ŸI>UsÉj€¤Ë€s÷€€,€s÷€€,€s÷€g€g€g€[€I>±$øŒa€[€s÷€= €,€g€0ÔjŒaY Ž ŽÉj€s÷€[€Œa€[€I>I>Usg€€,€0Ôj$Ÿ 57 ƒ+Ä~±²}ú—ƒ+Ä~7 €0Ô= Us7777øBUFR&bÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÂUUUUUUUUUU\cÆ1ŒcÆ1œç9Îsœç9Îsœç9Îs­kZÖµ­kZÖµ­kZÖµ½ï{Þ÷½ï{Þ÷½ï{ÞöB„!B„!B„!„!B„ Š•-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µå:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUPUUUUU@ð `0Ô$ŸI>0Ô= = I>= = [€Uss÷€Œa€Œa€g€= = 0Ô= = g€I>= UsUss÷€s÷€Œa€s÷€€,€€,€[€˜–€½5€±€ÕŸY½5€ÕŸ€±€˜–€ÕŸ€ô$çïçï Ž ޽5€$Ÿ 5 5 5 5 5= [ ŽèH¥$Œº¥$tP1-ÛºÛºÉj€çïçïÛºÉj€[€I>I>0Ô= I>Us[€½5¥$±YtP€ô$[æ±YY½5€˜–€€,€˜–€j+Ä}ú—ú—‚7 ƒ+Ä|j0Ô0Ô= = I>Us= = I>g€g€0Ô0ÔI>$Ÿ0Ô= $Ÿ0Ô+Ä+Ä| 5+Ä~±²+Ä|7777Ÿ€BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í0’I$’I$’I)$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUUUUUUUUUUUUUUeUUUUUUUUUPUUUU¢€`¢€ mƒ,üü mƒ,üü8€ m€%×€Jv€š¦\ÆJv€u0²9¾né'>šu‰u‰¦]u‰&0‘€Üò€™Ïhû\Æeu0\Æ\Æe™Ïehû\Æ2 €\Æ2 €Jv€e‘€Üò€õ\€Ê£é'€Üò€²9\Ʋ9šÖز9õ\€õ\€¾n™ÏÊ£é'€ÖØûûJÏJÏu‰>ó‚‚ö€v;c’¾iTÊüõµõµ×1>ó‚²ëŽLé€õµãfê¾Ç>š€õ\€Ê£é'ûû>š&0€õ\€õ\>šû&0&0>šJÏû>š&0€é'€š>A€%×€¢ƒ,üÿ,üü%×€hûõ\‘€ÖØé'€ÖØÖØé'€hûšÊ£²9u0u0²97777€BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í,0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUPUUUUUAUUUUUPUUUUUUUUUTð `½5€€,€gÂtPhÃh1-=bYI—h€ô$±€¤Ë€Œa€±€ô$ ŽÕŸ€˜–€Éj€ÉjY€,€Us0Ô$Ÿ[€0Ô+Ä+Ä|0Ô˜–€ÛºÉj€Œa€I>$Ÿ$Ÿj$Ÿ$Ÿ0Ô= Usg€UsI>0Ô0Ô+Ä+Ä|g€ۺI—UÌ€…I—=bI— ŽI—=btP[æ€ô$Ûº½5€€,€= = $Ÿ7 €…ú—€$Ÿ= ˜–€s÷€0Ôj 5 5$Ÿg€g€g€I>Us€,€I>$Ÿ0Ô[€= ˜–Ãô$ô$$ø[悽ç‚hth€Ûºs÷€= I>0Ô0Ô= $Ÿ$Ÿ 5j 5j+Ä~±²|±²}ú—€7777€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍD0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUTUUEUTUUUUUUUUUð aú—€j[€¤Ë€¤Ë€[€= = I>Us[€s÷€s÷€= g€I>[€[€0Ô0Ôs÷€€,€0Ô 5= g€ô$I—hUÌ=bÛº¤Ë Žô$$øUÌ1-çïUs$Ÿ$Ÿ0ÔUs[€Us$Ÿ+Ä}ú—‚7 €= $Ÿj$ŸUs= $Ÿ0Ô$Ÿ$Ÿ±²|0Ô= j$Ÿj0Ô$Ÿ 57 ‚7 ƒ+Ä| 5 57 ‚±²~7 ‚±²~7 ú—‚7 ‚±²}ú—ƒ+Ä|j$Ÿ0Ô$Ÿ$Ÿ= g€çï½5Y$ø$øŒº¥$€Ûºç€Éj€ÛºYh[æUÌÃY€,€jj+Ä|$Ÿ 5= ¤Ë€çïYÛºI>0Ô0Ô7777€BUFRöbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍX@"""""""$DDDDDDUUUUUUUUUUUUffffffffffffwwwwwwwwpŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUTAUUUUUUEUUUUTUUUPUUUð `0Ôs÷€€,€±€€,€½5€[€s÷€Us$Ÿg€çïÕŸ€Éj€Ûº½5€¤Ë€½5€ÕŸ€çïÕŸ€¤Ë€[€˜–€€,€I>Œa€½5€g€Œa€s÷€¤Ë€ÕŸ€ÕŸ€Us+Ä|+Ä~±²|j½5 Žô$¤Ë€Us¤Ë€Œa€s÷€[€Us½5€ô$±€0Ô= g€˜–€Œa€¤Ë€¤Ë€Éj€Us 5jj+Ä|jj= 0Ôg€$ŸI>= 0Ô= Us= $Ÿ$ŸŒa€çïô$€,€˜–€[€0Ô±²~7 €…ú—‚±²|[€Œa€g€= j 5$Ÿ+Ä| 50Ô$Ÿj$Ÿ$Ÿ 5±²}€…ú—ú—€…‚7 € 5€,€±€˜–€¤Ë€g€g€[€g€s÷€€,€Éj€77770BUFR&bÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍUUUUUUUUUUUUUUUUUUUUUUUU^sœç9Þ÷½ï{Þ÷½ï{Þ÷½ïz„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œc!@‹N•µÀ …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸!¦:ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUTTð `½5€Us0Ô˜–€½5€¤Ë€€,€I>[€0Ôj= €,€Ûºô$ô$±€˜–€˜–€¤Ë€½5€½5€ô$ ŽYY¥$‚²=»ÉÃhUÌYçïÉjY[æâ-h€½5€Œa€ÕŸ€½5€±€s÷€[€Œa€½5€Éj‚%Q¥}‚±²‚è¡Õøh€½5I—$øUÌ¥$ÉÃ[æh€ô$½5€çï¤Ë€ô$Éj€½5€gÂèH%Q€Þ‚‚²±Y¥$tP[æ=bŒº‚½Ž ŽŒa€s÷€˜–€Éj€Éj€Œa€¤Ë€Œa€ÕŸI—1-Ûº0Ô 5 57 ú—sú—ú—ƒ+Ä~±²~7 ‚7 ‚7 ú—ú—€…‚7 ú—ƒ+Ä|$Ÿjj 5+Ä~7 ƒ+Ä~±²|7777Ÿ€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@0$’I$’I$’II$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ç>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTPUUUUUUUUUUPUUUUUUUUUUUUUUð `$Ÿ= = 57 ‚7 € 5+Ä+Ä|$Ÿ$Ÿ0Ô±²|Us7 ƒ+Ä~7 ƒ+Ä~±²|I>s÷€±€¤Ë€˜–€˜–€g€g€Œa€g€Éj€˜–€[€= 0Ôg€€,€= UsUsg€[€I>[€s÷€Œa€s÷€±€g€[€½5€±€½5€s÷€Œa€Ûº ŽÃçï±€s÷ƒ+Ä~±²+Ä+Ä|€,€¤Ë€Ûº Ž1-ô$¤Ë€€,€s÷€€,€çï=b Ž=b1-h€…YÕŸ€ÕŸ€ÛºÕŸ€˜–€ÕŸ€ÛºÕŸ Ž Ž ŽÉj€¤Ë€Œa€˜–€Œa€¤Ë€½5€Œa€€,€½5€ô$h[æ$ø½5€[€Œa€[€Uss÷€Œa€s÷€[€s÷€$Ÿg€jUs7777²~BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@(0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’Im¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¥Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `€,€½5€¤Ë€€,€g€՟€çïÉj€¤Ë€s÷€$Ÿj+Ä}ú—ú—ú—‚7 ú—‚±²| 50Ô0Ô[€g€= 0Ô0ÔI>¤Ë€Éj€±€€,€[€ 5 5+Ä+Ä|$ŸUsŒa€±€¤Ë€€,€s÷€€,€[€I>I>I>g€I>UsçïÛºÛºô$s÷€0Ô$Ÿ±²+Ä|$Ÿs÷€Ûºçï±€¤Ë€Œa€€,€±€±€½5U̽5€ÕŸY=b˜ïŒº[æý5€Œa€½5€¤Ë€½5€ÛºÃô$çïô$±€g€g€s÷€Œa€½5€¤Ë€ÛºÃ²â-èHÉÃŒº$øçïÉj€½5Yh$øÉj€s÷€[€0ÔI>= $Ÿ0ÔI>j 5= g€j 57777²~BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@<0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm·m¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUDUUUUPUUUUUUUUUUUUUUUPUð c+Ä~7 ú—ú—ú—‚7 €0Ôg€±€ÕŸ€±€¤Ë€€,€˜–€€,€€,€¤Ë€½5€˜–€±€€,€[€[€j+Ä|+Ä~7 €Us¤Ë€ÛºÕŸ€Éj€€,€Œa€g€€,€±€½5€ô$çï½5€˜–€g€s÷€s÷€I> 5+Ä~±²+Ä+Ä| 5= [€[€[€g€UsUsI>= $Ÿg€g ŽŒº€…[æU̽5€I>= 0ÔŒa€ÕŸ=bŒºY= = $ŸI>g€˜–€çï$ø1-$ø½5€ô$ô$Éj€€,€±€g€Œa€= ½5€ô$ô$½5€I>0Ô[€j0ÔgÂYtP€= Ã$ø½5€Usú—‚±²~±²~±²|$ŸjUss÷€¤Ë€¤Ë€7777²~BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@T0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUPUU@UATUUTUU@EUUð `˜–€€,€¤Ë€½5€Éj€½5€çïô$½5€½5€Œa€0Ôjj0Ô€,€Œa€ÕŸ€Œa€j$Ÿ 5±²+Ä|$Ÿj[€0Ô0Ô= = $Ÿ7 €…ú—€…‚7 ‚7 €$Ÿ= Us0Ô 5 5+Ä+Ä|+Ä~±²|j0Ô$Ÿ0Ôj$Ÿ$Ÿ 5$Ÿ$Ÿ 50Ô+Ä+Ä+Ä~±²~±²~7 ƒ+Ä~7 ‚7 €…‚±²|I>= = $Ÿj= = $Ÿ$Ÿ$Ÿ 57 s€…sssssss€…‚7 ‚7 ƒ+Ä|+Ä|+Ä|Us[€€,€˜–€Us 5 5 5 5+Ä| 5j7777²~BUFR&bÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍB\ç9Îu­kZÖµ­kZÖµ­kZÖ·½ï{Þ÷½ï{Þ÷½ï{ÞùÎsœç9Îsœç9Îsœç;Þ÷½ï{Þ÷½ï{Þ÷½ï}ï{Þ÷½ï{Þ÷½ï{Þ÷€‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUTEPUUUUUUUUUUUTAð `0Ô= = ±²}ú—s€…ú—s€…€…ƒ+Ä~±²|j0Ô 5 5jjI>$Ÿ0Ôj+Ä|j+Ä}€…€…ú—‚±²}€…ú—sú—€$Ÿ+Ä~±²~±²~±²~±²+Ä}ú—ƒ+Ä+Ä|+Ä|$ŸŒa€I>±²+Ä+Ä+Ä|g€՟€ÛºÃçï ŽÕŸ€ÕŸ€¤Ë€UsUs0Ô 5±²| 5[€¤Ë€0Ô 5j±=bÉj€s÷$øÕøI—$Ÿj 5$Ÿ$ŸjUss÷€s÷€= +Ä~±²|= g€Œa€±€Usj 5 5+Ä~±²+Ä|±²~±²|+Ä|$ŸI>+Ä+Ä|7777Ÿ€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€0’I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¦5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTDUAUTPUUUUUU@Uð b7 €…€…ú—ú—ú—ssssss€…ss€…ú—‚7 ‚7 ‚7 €…€…€…sss€…ƒ+Ä|= 0Ô7 ‚±²~7 ‚7 ‚7 ‚7 ƒ+Ä+Ä~±²|+Ä|±²~7 ú—s€…s€…€…ƒ+Ä|$ŸUs0Ôj 5±²~±²|±²+Ä~7 ú—‚7 ‚±²~±²}ú—ssú—ssss‚±²| 5$Ÿ 5j$Ÿ+Ä| 5±²~±²|jI>= 0Ô 5j+Ä|j±€ÛºY±€s÷€[€Usg€= $Ÿ= g€UsI>$Ÿ$Ÿj0Ô€…ú—ú—ú—€ 5[€Éj€ÛºÕŸ€[€˜–€7777€BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTUUUT@@UUUUUUUUUUUUUUUUð `= 0Ô[€¤Ë€¤Ë€½5€ÛºI>s÷€˜–€= +Ä~7 ‚7 ƒ+Ä~±²}€…ú—ƒ+Ä|jg€[€I>UsUs= 0Ô= Us$Ÿ$Ÿ0ÔI>= +Ä+Ä}ú—€±²~7 ú—€ 57 ‚±²+Ä| 5 5j±²~7 ƒ+Ä|[€€,€j$Ÿ$Ÿ+Ä|$Ÿj 5$Ÿ0Ô= Œa€±€Œa€[€Usg€Uss÷€g€¤Ë€Éj€˜–€˜–€€,€ÛºÛºI—ô$Éj€ÕŸ€$ŸjI>Ûº[€Us= = Us$Ÿ0Ô$Ÿ0Ô0Ô 5 5Us[€$Ÿú—€…ú—€…ú—‚±²|= I>Œa€€,€s÷€˜–€˜–€½5€Éj€ÕŸUÌ[æ1-h€7777€BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€,0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUTUUUU@UUUUUUUUEð atP€ÕŸ€Œa€€,€€,€$ŸUs0Ô0ÔUsUs½5€Ûº¤Ë€[€I>Us[€Œa€€,€Œa€Œa€±€s÷€±1-U̱€[€I>0Ô$Ÿ+Ä|$Ÿ€,€½5€±€±€€,€Œa€UsUs€,€€,€Éj€ÕŸ€Œa€ÕŸ€ô$Y˜–€s÷€$Ÿ 5j+Ä~7 ‚±²| 50Ôg€˜–€Œa€˜–€Œa€€,€Œa€Œa€s÷€I>= 0Ô= = 5sú—ú—ssss€…€…ú—‚7 ‚±²~7 ‚±²|$ŸŒa€= = ±€˜–€˜–€s÷€Usj$ŸUs= UsI>$Ÿ$Ÿ0Ô= s÷€Éj€g€= jI>g€s÷€I>+Ä|= $Ÿ7777€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€D0’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠ2ÇBT¶5Ï„e:V׆B˜èJ–çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€C!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUEUUUUUUUUUUUUUUUPUUUUUUð `j$Ÿ[€ÕŸ€½5€s÷€$Ÿ 5= = Us$ŸUs ޽5€I>0Ôs÷€€,€I>±²|= ˜–€˜–€Éj€ÕŸ€çïÛº½5€½5€½5€±€ÛºÕŸ€[€€,I—çï=bÕŸ€¤Ë€ 50Ô+Ä|0Ôg€±€çïçï½5€±€s÷€Œa€½5€Œa€½5€Éj€ô$ô$ÕŸ€˜–€Éj€ÕŸ€±€±€ÛºÉj€˜–€€,€±€¤Ë€¤Ë€€,€€,€¤Ë€ÕŸ€Éj€I>UsUsg€€,€[€UsI>I>I> 5±²~7 ‚7 ‚7 ƒ+Ä|0Ô€,€Œa€s÷€s÷€s÷€Œa€[€I>I>g€˜–€˜–€˜–€g€[€Us= 0Ôj±²~±²~7 €+Ä|jI>g€[€¤Ë€¤Ë€s÷€7777€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€X0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUQUUUUUUUUUUUUð `[€I>€,€¤ËÃ=bŒa€€,€0Ô0Ô= $Ÿj 50Ô˜–Ã Ž ŽÃI—Ûº¤Ë€€,€€,€g€g€I>s÷€Œa€Œa€Us0Ô 5 50ÔUsg€˜–€Éj€¤Ë€¤Ë€s÷€I>I>˜–€€,€[€¤Ë€[€Us¤Ë ŽYÛºs÷€[€€,€I>0Ô$Ÿ+Ä|0ÔI>UsI>Uss÷€Us€,€g€[€Œa€g€˜–€±€˜–€I> 57 ú—€…€…€…ú—€ 5[€s÷€Œa€Œa€˜–€Œa€s÷€[€[€€,€€,€g€UsI>= 57 ‚7 ú—€…€…€…‚±²|0Ôs÷€s÷€Œa€˜–€¤Ë€½5€½5€½5€€,€€,€€,€g€0Ôj$Ÿ0Ô7777€BUFR&bÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í‚UUUUUUUUUUUUU]o{Þ÷½ï{Þ÷½ï{Þ÷½óœç9Îsœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{Þ€!B„!B„!BB„ ‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt)lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUDUUUUUUUUUUUUUUUUUUUUUUUð `0Ôjj 5jUss÷€Œa€½5€ô$ Ž$ø ޽5€çïÕŸ€¤Ë€±€Éj€±€Éj€˜–€Œa€Us0Ô+Ä|7 ú—ú—‚7 ‚7 ‚±²~±²|j$Ÿ[€= = 5Usj= s÷€I>UsjI> 5jjUsÛº ŽYÃçïI—tPI—[怅UÌ€…€…$ø½5€[€0Ôj= Éj€±€g€$Ÿ= g€Œa€s÷€s÷€s÷€s÷€ÕŸ€ô$UÌUÌtP€±=bY Ž ŽÛºÕŸ€[€˜–€Œa€g€€,€€,€Œa€¤Ë€Œa€Œa€Œa€g€I>±€Éj€Éj€ÕŸ€Éj€Éj€˜–€çïŒa€I>j0Ô 5$Ÿs÷€€,€˜–€7777Ÿ€BUFR¶bÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ 0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠ„­sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ ]ÃÏÞ?x /M`^šÀ½5èHÄé¬ ™p#`@@˜–I—²$ø @ øP6î€zÏ…† ôÖ?x 9ûÀa¨YI—1†é¬ » ¦°0Ô^šÀ˜–Ãn628)2à@@Œa€çï“.Ä´?x q°Èà3á@OX€ž±n6ˆ øPð 3á@^šÀ€,Yn6zÄIð€ 5O€j0Ô$ø†  @ @ 5j0Ô’|zÄ|(~ð#`9ûÀ0ÔYn6zÄ?x™p0Ô^šÀ±bÏÞ> ÓXŒ0 ReÀ¤Ë1-n6Ül ð /M`@@Ûº† 1†>ÆÐ/M`€,€˜–€ž±’|$ø @$Ÿoc ’|s÷€7777ŽBUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ 0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUTUUUPUUUUUUUUUUUUUUUUUð `˜–€0ÔI>= 0Ôs÷€¤Ë€˜–€I>g€= ±€ô$I—€…h ŽŒa€g€g€¤Ë€…‚t©‚bZ±€= UsŒa€¤Ë€€,€[€ 5jj 5+Ä~7 €jj 5j$Ÿ0Ô0Ô0Ôj 5 5 57 ‚±²~±²~±²~7 ‚±²|jI>$Ÿjj0Ô= 0ÔI>I>0Ô[€g€[€= = ˜–€Éj€±€±€[€= = 0Ô[€½5€ÛºçïY½5€˜–€¤Ë€s÷€I>[€Usg€˜–€ÛºÉj€ÕŸ€Œa€I>[€I>jj0Ô$Ÿ$Ÿ= Us$Ÿ$Ÿ$Ÿ$Ÿ$ŸUsUs= g€˜–€ÕŸ€ÕŸ€ÛºÉj€€,€7777>BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ80I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ …1Е-sáN•µÀ …1Ð¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTAUUUUQUUUUUUUUUUUUUUUUUUð `Us= jUsŒa€±€±€±€ÕŸ€½5€Éj€g€s÷€½5€ÕŸ€Éj€€,€¤Ë€s÷€s÷€s÷€€,€Us+Ä|= +Ä~7 €[€s÷€s÷€¤Ë€0Ô= g€€,€±€ÛºÉj€¤Ë€0Ô$Ÿ$Ÿ= g€7 €7 ‚±²|= s÷€˜–€Œa€Uss÷€[€Us0Ô[€Us€,€I>UsŒa€Œa€Œa€Œa€Œa€[€$Ÿ+Ä|$ŸI>€,€g€g€˜–€Œa€¤Ë€¤Ë€Éj€€,€g€s÷€€,€s÷€g€±€¤Ë€ÕŸ€s÷€[€s÷€g€$Ÿ0Ô[€Us˜–€Œa€½5€Éj€ÕŸ€½5€Éj€±€¤Ë€€,€[€0ÔI>[€[€0Ô 5j 5 5$Ÿ 5= g€[€I>7777>BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀL0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@UUU@TUUUUUUUUUUUUUUUUUUUUUð ` 5+Ä~±²~±²+Ä~7 ƒ+Ä~7 ‚±²|$Ÿs÷€˜–=bhI—çïÛº˜–€€,€[€Œa€g€= $Ÿ±²}€…€…ú—ú—€…€…‚7 €$Ÿ= $Ÿ 5g€I>+Ä~±²}ú—€ 5g€s÷€˜–€˜–€I> 5$Ÿ 5 5$Ÿ 50Ô0Ôj±€$ŸŒa€Us±€Œa€¤Ë€Us= €,€Éj€çïô$Ûº€,€s÷€˜–€Ûºçï$øUÌUÌçï$øI—€…tP=b½5ÃçïÕŸ€ÕŸ€ÉjI—±Yô}I—€,€˜–€½5€Éj1-UÌÛº1-1-=bUÌ€,€s÷€Uss÷€¤Ë€Œa€[€ÕŸtP=b ŽÕŸ€¤Ë€¤Ë€g€˜–€˜–€½5€s÷€Us7777>BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ`0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÛmÛ`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUPUUUUUUUUUTUUUUUUUUUUUUUAð `¤Ë€Éj€ÕŸ€[€I> 5€…€…€…ú—ú—€= I>I>$Ÿ= I>I>s÷€˜–€ÕŸ€çïg€= Us€,€Éj€Éj€ÕŸ€ÕŸ€€,€˜–€˜–€¤Ë€Œa€€,€Œa€½5€Œa€€,€s÷€g€s÷€s÷€I>= 0Ôj 5+Ä+Ä~±²}ú—‚7 €…€…€…ú—€…‚7 ‚7 ‚±²+Ä+Ä~±²+Ä+Ä+Ä| 5 5jI>Ûºçïñ€0Ô$Ÿ0ÔI>s÷€g€Œa€¤Ë€€,€Œa€g€[€= 0ÔUsg€€,€Usg€€,$øUÌUÌ=bÃçïÉj€¤Ë€¤Ë€ô$Y=bô$±€€,€g€[€˜–€s÷€[€˜–€çïý5€˜–€$Ÿ7 ‚7 €7777>BUFR&bÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÂUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï{Þ÷½÷½ï{Þ÷½ï{Þ÷½ï{ÞB„!B„!B„!„!B„!B„!BÆ1ŒcÆ0ŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èL"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUTUð `jI>s÷€[€Us$Ÿ0Ô$Ÿ= $Ÿ 50Ôg€= j$Ÿj 5 5j7 ‚7 ú—ú—ú—€ 50ÔUsg€[€Usg€€,€˜–€s÷€[€€,€˜–€±€±€¤Ë€¤Ë€¤Ë€Usjjjj[€[€s÷€s÷€[€[€I>[€g€I>Us[€s÷€Us= I>[€g€g€€,€[€I>= UsI>= [€I>[€UsŒa€g€¤Ë€±€s÷€g€s÷€Œa€½5€ 5js÷€Œa€s÷€Us0Ô 5 5€…ú—€±²~7 ú—‚7 ‚±²~±²~±²|I>I>$Ÿjjj+Ä}€…ú—€…€…€+Ä+Ä~7 ƒ+Ä| 57777Ÿ€BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í0’I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶Û’I$’I$’Km¶Ûm¶Ûm¶Ý¶Û`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®„e:V×D2ÇBT¶5Ï„gJÚà†B˜èJ–ÆÆt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@UQUTUUUUUUUUUUUUUUUUTð c+Ä+Ä+Ä~±²~7 €…€…€…€…€…€…ƒ+Ä| 5+Ä+Ä+Ä~7 ‚7 ƒ+Ä+Ä~±²+Ä|j+Ä~±²| 5+Ä}ú—€…s€…€…€…€…€I>I>= 0Ô 5+Ä|$Ÿ 5 5±²}ú—€…€…€…ú—€…€ 50Ô[€I>Us= j 5$Ÿ 5= = g€Œa€I>j= 5 50Ô€,€Œa€Œa€˜–€¤Ë€±€g€Éj€[ÉÂÊ½Ž‚Ê‚±²‚%Q Ž1-Œa€ 5jUs[€Uss÷€˜–€s÷€Œa€[€I>Usg€[€Usô$¥$=b¤Ë€Œa€[€Œa€Us0Ô= $Ÿ+Ä|7777BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í(0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð ` 50ÔI>$Ÿ+Ä~±²~7 ‚±²+Ä+Ä| 5 5jj 5 5 5g€g€ۺ€,€Us= I>0Ô= [€gÂâ-€…¥$h½Žâ-‚ çô}¥$€çï ŽÃI—1-[æ[æ€ô$½5€ÉjUÌçïÛº½5€ÕŸ€½5€ÕŸ€˜–€Ûºh=bY˜–€s÷€ô$I—çï½5Y ŽÉj€˜–€€,UÌ€…[æ€Ûº ޽5€[€Œa€ÕŸ€½5€¤Ë€[€ 5$Ÿ 5 5= g€€,€s÷€[€Œa€€,€s÷€= Us[€Œa€½5€±€€,€ŒaYÉØïI—$øY¤Ë€Éj€±€Œa€çï[ætP€Ûºs÷€˜–€¤Ë€s÷€±€˜–€[€[€7777BUFRæbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í<0$’I$’I$’II$’I$’I$’m¶Ûm¶ÛrI$’I$’Im¶Ûm¶ÛmÛm¶Ûm¶Û`‹:Zà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƺ×D2ÇBT¶6S¥mpC!Lt%Kc\øFà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUEUUUUUUUUUð aÃV%¥$€Ûº˜–$ø±€Éj€±€ô$Éj€€,€I>Us0Ô0ÔI>Us[€I>= 0ÔI>¤ËY€…€½5€±€= g€$Ÿ 5jÉj€±€ÛºçïYŒa€g€€,€[€I>= = [€g€ۺ1-ô$$ø1-ô$˜–€g€€,€Œa€€,€½5€çïYô$Y€,€Us0ÔI>0Ô0Ô$ŸI>0ÔjjUs¤Ë$øI—±€s÷€0Ô0Ô= g€UsÕŸ€ô$ 5±²| 5 50ÔUsçn€ô$çïÀ…=bçïô$=bŒº=bÉÃâ-=b±€s÷€˜–$ø[æY˜–€€,€[€[€[€s÷€ÕŸ€ÕŸ€çïÉj€g€s÷€7777BUFRöbÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍT@"""""""""""#333333333334DDDDDDDDDDDEUUUXˆˆˆˆˆˆ™™™‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜ëc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUPð `€,€s÷€s÷€0Ô+Ä|j±²+Ä|[€½5€ÕŸYŒa€˜–€Œa€¤Ë€Us¤Ë€Éj€±€˜–€˜–€½5€ÛºÕŸ€ÕŸÃçïÉj€s÷€Us[€0ÔI>= I>0Ô 50Ôj$Ÿ0Ô$Ÿ 50Ô0Ô[€g€[€[€= 0Ô+Ä| 5+Ä~7 ƒ+Ä+Ä|0Ô= g€€,€I>I>0Ô= s÷€˜–€Éj€ÕŸ€Éj€˜–€[€s÷€I>0ÔUs€,€s÷€g€$Ÿj$ŸUs[€Œa€±€¤Ë€Œa€Us$Ÿ 5I>Y½5€€,€½5€€,€˜–€½5€˜–€g€= €,€¤Ë€±€j$Ÿ0ÔUs0Ô[€Us±ÃÕŸ€±€˜–€[€ 5±²}€…€…‚±²|jŒa€7777BUFR&bÿ« fÍ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï{ÞûÞ÷½ï{Þ÷½ï{Þ÷½ï!B„!B„!BˆB„!B„!B„! cÆ1ŒcÆ0Št%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUU@UUð `s÷€[€s÷€¤Ë€¤Ë€¤Ë€±€½5€½5€Éj€ô$Yh¥$=bYÉj€˜–€I>$Ÿ 5 5j€,€Œa€I>$ŸjI>0Ô= g€[€I>= I>0Ô 5ú—ú—‚7 s€…ú—€$Ÿs÷€Œa€s÷€s÷€g€I>$Ÿ0Ô= UsŒa€Œa€¤Ë=b=b¤Ë€˜–€Œa€¤Ë€Éj€½5€¤Ë€˜–€s÷€ÕŸ€¤Ë€˜–€[€[€UsUs0ÔUss÷€¤Ë€˜–€Œa€±€˜–€Us$Ÿ±²~7 ‚7 ‚±²}ú—‚±²|= g€Œa€˜–€€,€s÷€[€UsUs[€[€¤Ë€€,€g€Us= I>Usj€…‚±²~±²+Ä|I>g€½5€¤Ë€g€I>0Ô0Ô$Ÿ0Ô0Ô7777Ÿ€BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶Ûm·`ŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øÊt­®ˆd)Ž…±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUTPUUU@UUUU@UUUUUð `0Ô[€¤Ë€˜–€¤Ë€ô$ÛºÛº¤Ë€Us0Ôj 50Ô[€˜–€ÕŸ€½5€ÕŸ€˜–€[€[€€,€€,€Œa€Éj€ÕŸ€Éj€ô$Yô$çï½5€±€ÛºÕŸ€˜–€Œa€€,€[€Us= 5±²}ú—‚±²|+Ä+Ä|j 50Ô 5 5+Ä+Ä}ú—s€…€Œa€Œassú—ú—ƒ+Ä|jj 5$Ÿ 5 50Ô 5j€,€g€Usj+Ä}ú—€…ƒ+Ä| 5€,€½5€Éj€±€[€g€g€[€UsI>[€s÷€€,€s÷€I>s÷€[€0Ô= +Ä~±²+Ä|$Ÿg€Œa€½5€[€UsI>[€UsÕŸYYI—0ÔI>½5€Ûºô$ÛºÕŸ€7777 BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@(0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUPUUUUUUAUUUAPAUPUð `±€¤Ë€¤Ë€˜–Y=b1-çïçïs÷€€,€s÷€€,€±€ÛºYÕøÉØï[æ Ž½5€¤Ë€ÕŸ€Œa€= g€½5€±€½5€ÕŸ€½5€ÕŸ€ÛºÛºô$$øÃ½Ž½Ž ŽI—U̱€€,€= ú—€…€…s‚7 €0ÔŒa€˜–€±€¤Ë€Œa€½5€g€Us$Ÿ= I>UsI>= UsŒa€˜–€Œa€[€$Ÿ+Ä}€…€…ú—€j 5j 5 5+Ä+Ä| 5$Ÿ= = I>[€s÷€0Ô$Ÿ€,€g€I>g€ 5±²}s€j[€= €…ú—ú—‚±²~7 ‚±²|7 ƒ+Ä|= [€€,€Ûº¤Ë€¤Ë€I>+Ä~±²~7 €j0Ô= ±€Éj€€,€g€7777 BUFRæbÿ« fÍ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@<0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUUUUUUUUUUUU@UUUUPUPð `= 0Ô= 0Ô0Ô[€g€Œa€Œa€Us[€0Ô[ƒ+Ä}ú—‚7 ‚7 ‚7 €= Œa€˜–€s÷€[€I>I>= = I>UsŒa€Œa€çïÃô$½5€±€s÷€j 5±²~7 €g€½5€çï½5€½5€çïÛº½5YYÛºÉj€ÉjYÛº Ž Žs÷€g€€,€±€s÷€Usg€€,€¤Ë€˜–€çï$ø=b=bÕŸ€$ŸUs½5€½5€¤Ë€½5€˜–€[€= j±²}ú—€…ss€…€ 5g€€,€±€€,€[€Usg€0ÔI>I>UsI>$Ÿjj 5 50Ô±²~±²+Ä~7 ú—‚7 €j[€0Ô±²~7 ú—ƒ+Ä| 5j7777 BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í@P0’I$’I$’I)$’I$’I$›m¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹)Ò¶¸2ÇBT¶5Ï„e:V×D2ÇBT¶B2+k€" c¡*c\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUUUUUUUUUUUUUUUUUTUUUTð ` 5$Ÿ0Ô= 5$Ÿ= [€j= [€s÷€Œa€˜–€0ÔŒa€Œa€Œa€Œa€Œasú—€0ÔI>0Ôs÷€= 0Ô= [€[€I>= Us¤Ë€çï$øŒºUÌ= $Ÿjs÷€I>Us[€$Ÿg€= $ŸI>˜–€= $Ÿ0Ԥˀçï Ž1-$øUs 5j 5j= Us€,€[€Us$ŸI>j0Ôg€$Ÿj$Ÿ€,€Éj€ô$$øô$s÷€j$Ÿ[€[€s÷€¤Ë€Œa€ÕŸ€Ûº[€[€[€= 5j+Ä~±²| 50Ô€,€˜–€€,€s÷€[€s÷€g€Us€,€s÷€˜–€˜–€±€g€$Ÿj±²~7 ‚7 ‚±²}sú—ú—€s÷€7777 BUFR&bÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍBUUU\ç9Îsœç9ÎsœëZÖµ­kZÖµ­kZÖµ­o{Þ÷½ï{Þ÷½ï{Þ÷½óœç9Îsœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{Þ€Št%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUTUUð `€,€€,€UsUs0Ô€,€UsUsg€€,€[€s÷€g€= 0Ô$Ÿ+Ä| 5+Ä+Ä~7 € 5¤Ëà ŽI—Ã0ÔUs[€g€I>˜–€Œa€Œa1-tPI—±€$Ÿjjs÷€¤Ë€Us= = €,€$Ÿ 5Us¤Ë€¤Ë€˜–€˜–€çï Ž¥$‚â-ô}Õø±YU̽5€= j0Ô0ÔÉjÃ[æ=bUÌ=bÕŸ€çïtPUÌtP½ŽÕø˜ï[æI—ÕŸYçïô$½5€±€ÛºÉj€Éj€Ûº Žô$ÕŸ€Ûºô$ÃUÌô$½5€Ûº¤Ë€Œa€g€UsI>= 0Ô$Ÿ 5±²+Ä|j0Ô0Ô= 0Ô0Ô= I>0ÔUsI>7777Ÿ€BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUUUUUUUUUUUUUUUð `[€s÷€¤Ë€˜–€€,€½5€UsŒa€Usj±²~7 ‚±²|j˜–€ô$$øÃÉj€½5€½5€½5€ÕŸ€Ûº Ž=bUÌh˜ïŒºtPhUÌYô$ÛºÛºÉj€çï1-I— ŽÛº ŽÛº¤Ë€Éj€ô$ Žô$ ŽÃ Ž Ž$øÛº½5€I>s÷€Œa€€,€UsŒa€Œa€Œa€˜–€g€[€s÷€g€g€s÷€Œa€€,€Œa€Œa€˜–€Us$Ÿ7 ú—ú—ú—€…ú—‚±²}€…€$Ÿ= $Ÿj0Ô0Ô= = [€± Ž1-I—ÃYô$±€˜–€[€j$Ÿ[€¤Ë€Éj€çïÉj€¤ËYh=b[æ[怅1-çïÛºÛº€,€Us7777sBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€0I$’I$’I$”’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©l|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUU@UUUUUQUUUUð `j 50Ôg€՟I—1-Ãñ€Œa€s÷€g€g€Œa€Ûºô$ô$ÕŸ€˜–€Œa€¤Ë€[€ 5$Ÿ0Ô 5Usçï=b=b[æ€Ûº¤Ë€±€ÛºÉj€Ûº ŽhUÌ1-$øÕŸ€˜–€¤Ë€UsI>jI> 5j€,€±€Œa€I>¤Ë€€,€g€½5Y ŽÉj€¤Ë€Œa€€,€0Ôú—s€…s€Œaú—€j±€¤Ë€¤Ë€€,€I>Us= 0Ô= s÷€Us[€Œa€Œa€I>Usg€I>$Ÿ+Ä|UsŒa€Œa€¤Ë€˜–€˜–€¤Ë€Ûº$ŸI>I>Œa€€,€g€0Ô 5±²|+Ä}ú—€…‚±²}sú—ƒ+Ä~±²~±²|$Ÿ7777sBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€00’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUTUUUUUUUUUUPUUUýà` 5jj¥}|0ÔI>˜–€˜–€½5€Ûº±€˜–€[€OX€0Ô 5j 5$Ÿs÷€½5€±€¤Ë€€,€g€g€g€¤Ë€˜–€¤ËYà ŽÉj€½5€[€ 5I>€,€˜–€˜–€˜–€½5€çïô$1-[æÃô$Yô$ô$ô$$ø$øô$½5€±€€,€I>$Ÿ¥}~+k€j[€Œa€¤Ë€˜–€€,€g€OX€OX€I>g€[€€,€¤Ë€Œa€€,€s÷€g€[€[€I>= $Ÿ$Ÿ= [€[€OX€g€[€€,€Œa€s÷€Œa€Œa€˜–€±€€,€€,€g€OX€[€$Ÿj+kîbtP€ú>‚+kƒ|$ŸOX€[€I>I>= 0ÔI>OX€€,€½5€Ï…7777sBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€D0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÛnÛ`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ö×D2ÇBT¶5Ï„e:V×D2ÇBX×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUTUUUPTEUUUUUUUUUð aYÃô$çï¤Ë€±€s÷€˜–€Œa€s÷€= [€g€s÷€½5€ÕŸ€ÛºÕŸ€ÕŸ€Éj€çïs÷€˜–ŒºtPhŒº[æI—I—Ã$øÛº€,€[€[€Œa€˜–€Œa€½5€…˜ï€Œa€I>s÷€½5€˜–€½5YÉj€j+Ä}€…€…ú—s€Œa€Œaú—‚±²|jI>Usj$Ÿj 5 5$Ÿ$Ÿ= 0Ô= $Ÿ+Ä~±²}s€Œa€Œa€Œa€O€Œaƒ+Ä|[€˜–€[€= +Ä|+Ä|= [€Éj€ÛºÛºÕŸ€½5€˜–€€,€UsUs= j[€s÷€˜–€±€Éj€½5€0ÔUsg€[€˜–€Éj€ÕŸ€ÛºÛºÉj€Ûº±€¤Ë€±€˜–€Œa€Œa€7777sBUFR¶bÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í€\0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]’ÕÐÆ~ðýà5gà9ûÀ¤ËÃbZÝÐÈà!‘ÀC#€mÝÕŸI—ÄdÆ~ðB@ 5·ÐdpÈà 2Z 9ûÀgÂÓ.é¬'¬@Us’|=bJIc¾ ¢„Йp&% LK@˜–’Õ28 'À¾h+|ÐC#€€,€Ûº’ÕddpÐ+|ÐZàº(AÉà oš 'ÀŒ0w@#`F0ÀŒa€·ÏÞÄ´ –¨#`c. ÀBÀô$·ô$Ä´?x'¬@OX€˜–ÃèHnèˆ Ð#`@@s÷€Ï…²¬ü Yø&% C#€ 5I>I>Ÿ d ‰h )2àLK@Œa€zÏÞ«˜Ið ®`O€-ÆÀs÷ÃÏÞ&\ Œ0B@ 5$Ÿ7777€˜BUFRbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!²LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í‚UUUUUUUUUUU]ï{Þ÷½ï|ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷¾÷½ï{Þ÷½ï{Þ÷½ï{ÀB„!B„!BŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ `0Ôj€,€ÃPÏ…çïÏ…ô$çïô$Ï…ÃPÏ…½5€½5€½5Y[悲ÏÞ ŽÃP¤Ë€Ï…çïçï$øC|[æ1-htPh[ætP1-1-1- ŽY$øŒºÉØïtPC|1-O±Ã1-Ã$ø1-[æ=b=b$øÛºô$ÛºçïÏ…Ï…½5€Ï…1-ÏÞƒuu±²˜ïO±tP1-htP‚‚1†ÜlIð½ŽÉÃYÛºY±€ÃPÏ…$øh˜ï‚¥}‚htÏÞ$ø Ž Žçïۺυ±€¤Ë€˜–€˜–€Œa€Œa€[€C#€= = $Ÿ0ÔC#€C#€= = = = 0Ô= OX€jOX€C#€s÷€7777= BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS S\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUUUUUUUUUTUUUUUUUUUUUUUUTýà`g€g€$Ÿ~+kîb‚¥}|= ±€çï¤Ë€s÷€Œa€˜–€OX€OX€[€Ï…çïçïÉj€±€Œa€Œa€s÷€s÷€= jOX€OX€OX€€,€€,€s÷€€,€g€[€s÷€Œa€˜–€¤Ë€½5€ÛºçïçïÏ…¤Ë€¤Ë€˜–€€,€s÷€= tP‚+k€= €,€Œa€˜–€€,€¤Ë€½5€Ï…çïÏ…˜–€g€g€I>I> 5j~¥}|$ŸÉj€Ï…O±1-I—ô$ô$Ï…ô$=b[æ˜ï½ŽhŒº€…€½5€˜–€˜–€Œa€€,€˜–€˜–€s÷€Œa€Éj€ô$ô$çïÏ… ŽI—O±1-=bI—çïÛºçïô$YÛº˜–€j}îbtPtP‚+k€7777= BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ 0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUQUUUUUUUUUUUUUUUUUUUUUUUUð `[€[€I>I>[€[€= 0Ô¤Ë ŽÀ,€I>s÷€s÷€[€Usj+Ä|±²~±²~7 ssú—ú—€= $Ÿg€g€s÷ ŽYñ€¤Ë€[€$Ÿj 5±²~±²|0Ô½5$ø1-=bçïÕŸ€½5€ÕŸ€Éj1-h=b$ø ŽÛºÛºÃô$½5€g€g€= [€s÷€±€çïYô$çïYY$øô$À…€…I—[æ1-I—=b ŽÛºÛºÕŸ€Éj€±€½5€çï1-tP=b1-I—[æ˜ï¥$[æ±Y‚V%½ŽhhtP$ø1- ŽYçïçïÛºÃ Ž½Ž½Ž€ô$ÛºI—1-I—7777= BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ40I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶àŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUTUUUUUQUUUTð a[æhÕø‚ çÕøèH¥$€…€…$øYYô$ÕŸ€çïô$=b[æ=b Ž Ž Ž1-1-UÌI—1-Éj€½5€½5€˜–€˜–€€,€s÷€= g€Œa€= Usg€½5€çïÛºÕŸ€€,€˜–€s÷€Ûºô$ÛºÉj€±€Œa€s÷€g€[€I>= 0Ôj+Ä}€…s€O€…‚7 ‚±²+Ä|0Ô= 0Ô0ÔI>I>= s÷€UsI>Us$Ÿ 5±²}ú—ƒ+Ä~7 € 5= €,€±€s÷€˜–€g€g€s÷€˜–€ÛºçïÕŸ€½5€±€±€s÷€g€0Ô0Ô 5 5+Ä|I>g€Œa€g€[€s÷€s÷€g€€,€˜–€˜–€Œa€Œa€Œa€j7 €7777= BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀL0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUUUUUUUUUUUUUUUUUUUUUUUUTð b7 €…€…‚7 ‚7 ‚±²|= g€[€€,€±€Éj€Éj€½5€Éj€Éj€½5€˜–€s÷€UsI> 5+Ä+Ä| 5j 5 5Us˜–€Ûºô$UÌŒºtPŒº¥$¥$¥$h[æÃô$Éj€€,€[€I>s÷€€,€˜–€½5€½5 ŽçïÛºçïçïÉj€½5€ÕŸYY Ž Ž=bI—[æUÌI—1-[æUÌI—=bUÌhâ-‚ 瀅 ŽÃ ŽçïYÃô$Ûºçï Ž$ø1-Ûº½5€[€±€g€g€[€Usg€¤Ë€±€€,€g€€,€€,€€,€±€½5€ô$ ŽÛº€,€s÷€€,€UsI>0Ô= j±²~±²|js÷€±€7777= BUFR¶bÿ« fÍ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÀ`0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠ•-Œ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýà]I—%ªKT ¦°,@ LK@€,€çﲟ¼È~ð9ûÀg€Éj’Õ%ªKT ÓX-P,@ LK@€,òd L¸Œ0&% LK@˜–Ã1†c Æ,@ F0ÀŒaÓ.&\ –¨ð ,@ X€@ÛºŸ nè¡ ~ð!‘À@@Œa€çïÏÞŸ¼ÝÐ » ð = zçïÏÞnè¡ ~ð!‘ÀF0À€,Y²28 }ŒE+|ÐOX€¤ËO±‚Ÿc“àÈw@6î€s÷€ÉjÏÞddp øPŒ0 -ÆÀ¤ËŸ “àÝÐ –¨ 6î€LK@Œa€çïô$èH† B@j0Ô0Ô0Ô† |(Ð/M`dµ@½5bbZ&\ ÓXw@@@s÷€Éj€7777€sBUFRöbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍÂUUUUUUUUUUUUUUUUUUUUUUUUU^sœï{Þ÷½ï{Þ÷½ï{Þ÷½B„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œd!@‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƺ”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@)2à]1-²Ÿ¼?x q°'¬@F0Às÷€ž±za¨ @-ÆÀ€,òŸ¼ ‰h„€F0À†GY²dÆÈà„€-ÆÀUsž±YŸ c ~ð)ö0Vù s÷Y·tnè€ 5w@9ûÀs÷€ÛºUÌbZ>èH @ã`gÂC|‚=»>|( øP#Û°] •‰AY1†¬J º<û)ö0G·`zÏ…Ÿ >W0 ‰hj-ÆÀ-ÆÀjUs ޏØB@#Û°G·`†G Ž=»¬J }Œû.Š`!`†GÛº=bÏÞÜl¸Ø øPð '¬@6î€Us ŽzÄÈÖ -ÆÀg€υn6>¡ tx9ûÀwÀÕŸ˜ï‚è¡>ÆdpB@(oF0Àmݪæ7777X€BUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUPUUUUPUUUUUUUUUUUUUUýà`Éj€½5€çïYçïÛºÛºYYÛº Žô$Y ŽYô$YÉj€Œa€[€= 5~+k‚+k€= OX€OX€g€ۺ€,€€,€¤Ë€ÉjY±€±€˜–€¤Ë ŽÛºŒa€g€s÷€[€0Ô|ú>€€,îbîb€j 50ÔI>OX€= OX€OX€I>$Ÿjjjj 5|ú>€€,tP‚+k€I>¤ËYυۺυÉj€¤Ë€Œa€˜–€Ûºô$½5€s÷€[€[€$Ÿ0Ô|ú>îbîb€ 50Ô˜–€ô$[æYçï ŽÃô$ Žçïçï±€Œa€g€I>Œa€Œa€OXîbtP€ú>îbîbƒ|I>½5€½5€¤Ë€[€OX€77770ÀBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í(0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUPUUUUUUUUUUUUUUUUUUUUUUð `I>UsI>I>Œa€±€˜–€ÛºÃUÌô$s÷€j+Ä~7 €…€g€¤Ë$øY½5€±€Éj€½5€Ûºs÷Yô$½5€€,€g€$Ÿj+Ä+Ä~±²+Ä+Ä|ŒaÃ=b1- ŽI— Ž$ø1-[æ˜ïŒºŒº˜ïtPtPh¥$hI—$ø Žô$ÕŸ€ô$Ã[æ=bUÌUÌhhUÌU̘ïhŒº¥$[æI—1-1-ÃÃô$ÕŸ€±€½5€Ûºçï Žô$I—Õø[æÃYçïô$çïÕŸ€ÕŸ€Éj€ÛºÉj€= 0Ô$Ÿ 50ÔÉj€ô$ Žô$ç€Œa€s÷€€,€Œa€±€¤Ë€Œa€¤Ë€˜–€77770ÀBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Í<0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `j 5+Ä~±²}€…sss‚7 ƒ+Ä|0ÔŒa€½5€Œa€0Ô 50Ô$Ÿ$Ÿ0Ô0Ô$Ÿ$Ÿ= = = 0Ô$Ÿ$Ÿj 5 5+Ä| 50ÔUs= Usg€Œa€˜–€±€±€±€±€±€±€¤Ë€¤Ë€˜–€˜–€˜–€g€g€[€Usg€g€˜–€¤Ë€¤Ë€¤Ë€˜–€¤Ë€±€½5€Éj€ÕŸ ŽÕŸ€çï ŽYYà Žçïô$çïçïô$Y=b¥$hUÌhhUÌh±Y[æ ŽYYô$ÕŸ€±€±€Éj€Œa€s÷€= I>= [€s÷€±€±€ÛºÉjYçïY Ž Ž$ø1-Ãô$Y$ø1-UÌ1-1-$ø77770ÀBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍT0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUTPð aI—1-UÌI—[æI—$ø1-Y¤Ë€¤Ë€½5€½5€˜–€Œa€Œa€˜–€s÷€Us˜–€½5€½5€Éj€½5€˜–€ô$ô$±€±€¤Ë€Œa€Œa€Ûº½5€±€½5€¤Ë€˜–€¤Ë€±€¤Ë€±€Éj€Ûºô$ô$½5€[€[€˜–€ÛºYUÌ=bI—$øÛº1-çï ޱ€€,€€,€½5€½5€€,€j$Ÿj0Ôj$Ÿ±h˜ï1-Ûº±€±€˜–€€,€¤Ë€˜–€0Ô 5±²}ú—€…€…ú—‚7 ‚7 ‚7 €…‚7 ‚7 €$Ÿ7 ‚±²+Ä|jI>j 5±²+Ä~7 ú—‚7 ú—€…ú—ú—s€…€…€…€…€…€…‚7 ‚±²+Ä|0Ô0Ô77770ÀBUFRæbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Íh0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×Â2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUEUUUUUUUUUUUUUUTUUUUUUð `= [€I>Us[Y ŽYÛº¤Ë€Œa€$Ÿj±²|7 €[€s÷€çï½5€½5€½5€±€˜–€±€½5YÃçï½5YçïYô$½5€ÕŸ€˜–€[€0Ô±²|= g€¤Ë€s÷€g€s÷€g€[€I>[€[Yô$½5€¤Ë€[€Us€,€˜–€çïŒa€I> 5j±€ô$I—=bÃô$UÌUÌtP=bÃçïçïçïÕŸ€s÷€[€0Ô+Ä~±²}ú—€…€…€…‚±²|= [€s÷€s÷€˜–€±€˜– ŽÃÕŸ€˜–€= ±²}s€…‚7 ssssú—€0Ôçï1-±€½5€Œa€±€ÉjUÌhŒºh$øô$ Ž77770ÀBUFRfbÿ« fÍ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÍUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTD»_x„!B„!B„!BB„!B„!B„!ŒcÆ1ŒcÆ1ŒcÆ2„!B„!B„!B”¥)JP‹k„C!Lt%Kc\øJt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUETUUUU@UDE@UUUUUUð `ô$çïŒa€g€[ƒ+Ä| 5[€[€Usj+Ä}ú—ƒ+Ä+Ä|±²}ú—s€O‚±²|s÷€s÷‚7 ƒ+Ä}€…s€…‚7 €…€I>±€çïŒa€ÕŸUÌÕŸ€Ûº½5€½5€ÕŸ€¤Ë€€,€¤Ë€0ÔI>g€[ú—s€Œa€O€Osú—€g€I>$Ÿ 5+Ä|±²~±²|0Ô7 ú—‚7 ‚7 ssú—€…s€…€…ú—ƒ+Ä~7 €+Ä| 5 5+Ä| 5$Ÿ€…ú—€…s€…€…ss€…€…s€…‚7 €Us Ž[æ$øÕŸ€½5 ŽŒº‚%Q±Y±YŒºtP[æUÌh ŽÉj€[€[€Œa€[€I>Œa Ž$ø7777BUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUUUUUTUUUUUUUUUUUUUUð a€…¥$UÌ ŽÕŸ€Éj€ô$ô$Éj€ÕŸ€½5€Éj€çïÃY€,€I>ssú—‚±²|= ô$çïÕŸ€¤Ë€€,€[€s÷€¤Ë€ô$±I—½5€Éj€½5€Us[€$Ÿú—€…€…ú—‚±²|0Ô½5Y=bY˜–€[€I>I>Œa€±€½5€Œa€€,€I>0Ô$Ÿ$Ÿú—€Œaú—€Œa€Œa€Œa€Œa‚±²|Éj€ô$¤Ë€s÷€€,€Œa€€,€Œa€ô$UÌYÕŸ€½5€±€¤Ë€€,€±€s÷€= 0Ô0Ô0Ô$Ÿ= s÷€˜–€±€€,€Œa€˜–€¤Ë€½5€ÕŸ Žçïô$Éj€ÛºÕŸ€Éj€˜–€±€Œa€I> 5j0ÔUsg€Œa€s÷€g€[€s÷€˜–€˜–€s÷€7777BUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@,0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@UUUUUUUUUUUUQUUUUUUUUUUUUUTð `€,€˜–€¤Ë€˜–€Œa€$Ÿjj±²}ú—ú—€= I>½5YUÌ1-çïÕŸ€±€¤Ë€¤Ë€¤Ë€½5€çïÛºÉj€˜–€˜–€s÷€0Ô$Ÿ= Us= Œa€s÷€€,€Œa€˜–€˜–€˜–€±€½5€Éj€Éj€Œa€ÛºÛºÕŸ€½5€˜–€[€= $ŸUs= 0Ô 5= 7 €= €,€Œa€I>$ŸUs€,€¤ËY=b Žô$Ûº¤Ë€¤Ë€$Ÿú—€…€Œa€…€0Ô¤Ë1-1-ÕŸ€½5€Éj€½5€±€çï$øUÌäˀ±€Ûºçï[€= 5s€Œa€Œa‚7 €= ±€çïÛº˜–€¤Ë€˜–€Œa€Œa€¤Ë€±€˜–€¤Ë€ÉjYÉj€½5 Ž Ž+Ä|7777BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@D0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUQUUUUPUUUUUUUUUUUUð aú—€…€…€…‚±²|I>¤Ë€¤Ë€s÷€g€g€€,€Œa€€,€Œa€€,€±€Œa€½5€Éj€Œa€I>0Ô±²}€…s€Œa€…s‚7 €g€[€= UsUsg€Œa€I>= 0Ôj 5 5+Ä|j±²~7 € 5g€çïô$Ûº Žô$±€±€ÕŸ€ô$YÃÃŒa€$Ÿj7 ‚7 ƒ+Ä|0Ô+Ä|€,€ô$h[æ=b$øtP[æUÌhtPÕø‚V%t©‚ht‚1†ÉØï[æÃYYÕŸ€¤Ë1-UÌtPtPtPÃ$ø$ø Ž$øI—=b=b ŽYYÕŸ€±€g€ 5ú—€+Ä|Œa€¤Ë€Ûºçï7777BUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@X0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥µÏ„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUAUUUUPUUUUUUUUEUUUð `±€±€½5€Éj€Éj€ÛºÕŸ€çï Ž=b½5€½5€½5€Éj€ÛºÛºÕŸ€Éj€±€±€ÉjY$ø ŽY±€˜–€Œa€˜–€€,€±€ÕŸ€¤Ë€½5€Éj€ÕŸ€ÕŸ€Ûºô$çï$ŸŒas€UsÉj€ô$ô$çï±€Œa€g€g€˜–€¤Ë Žçï±€˜–€€,€[€$Ÿ±²~±²}€…ss€Œa‚7 ‚±²|= I>$Ÿ0Ô0Ô7 ‚±²~7 ‚±²+Ä| 5UsI>±€g€= j 5I>0Ôs÷€ô$htP˜ï˜ï€çïŒa€g€€,€±€¤Ë€€,€Ûº±€¤Ë€˜–€Ûº˜–€0ÔI> 5+Ä| 5Us½5I—h[æ=bÃUsUsŒa€€,€½5Y7777BUFRbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!²LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎBUUUUUU]kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½ï½ï{Þ÷½ï{Þ÷½ï{ÞðB‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð `çïÛºUs$Ÿ0ÔI>¤Ë€˜–€UsŒa€çï Ž=b=bŒº½ŽèHâ-$ø[怅¥$½Žâ-˜ï€…˜ï˜ï€…[æhI—ÃY[æ˜ïÕøÕøèH±YÕøÕøÕø±YtP˜ïâ-¥$±YŒºŒºŒº±YÉ çÕø˜ïhhh€…ÕøèHô}²¥$ÕøÕøÉÃèH²ô}½ŽÉ ç²Õø€…¥$ŒºtP=bçïÛºÛºg€[€s÷€g€= I>j0Ôs÷€˜–€€,€Us= I>g€½5€Us$ŸUs= 0Ô$Ÿg€¤ËYçïs÷€¤Ë€€,€s÷€˜–€½5=b¥$±Y€…€…h1- ŽÃÛº7777BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ2ÇBT¸Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUTUUUUUUð `±€UsUsÕŸ€Éj€çï Ž ŽÕŸ=b1- Žô$ô$à ŽY$øYYô$$øUÌ%Q1†1†½Ž€…tP€ô$ÃUÌ½Ž¥$±Y€…=bhhÃ Ž ŽYYçïÛºçï[ætP˜ïUÌtPI—UÌY1-UÌU̘ï¥$€…Œº˜ïtP=b=bYÕŸ€±€ÕŸ€ô$=b½ŽÉÃI—1-1-1-1-$øI—[挺€…[ætPÃÕŸ€¤Ë€˜–€= +Ä+Ä|[€½5ÃÕŸ€€,€€,€g€Œa€Œa€Éj€Éj€Ûº¤Ë€¤Ë€€,€UsUsj+Ä}ú—s€…ú—€ 5 5s÷€Éj€˜–€Œa€UsI>I>0Ô[€7777±YBUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀0I$’I$’I$”’I$’I$’I&Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„ÆS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUU@UUUUUUUUPUUUUTUUUUUUð `¤ËY$ø1-htPI—s÷€Us€,€[€j±²+Ä|0ÔI>$Ÿ 5$Ÿ0Ô0Ôjjs÷€Éj€Œa€˜–€g€s÷€€,€s÷€$Ÿj±²}€…s‚7 €[€±€çïÛºÛºô$çïÕŸ€ÕŸ€ô$Y ŽÃô$ÕŸ€¤Ë€Œa€g€I> 5$Ÿs÷€çï1-$øÃYÉj€Ûº½5€Œa€Us$Ÿ+Ä~7 ‚7 ú—‚7 €= ˜–€¤Ë€Œa€g€s÷€g€s÷€¤Ë€±€ô$$øÛºs÷€Ûºçï½5€g€= +Ä~±²~7 ƒ+Ä|g€՟$ø[æ€ÕŸ€¤Ë€Œa€¤Ë€½5€Œa€¤Ë$ø=bà ŽÛº±€Œa€g€€,€g€I>I>= Œa€7777±YBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀40I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’[m¶Ûm¶ÐŠt%LkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUU@UUUUUUUUUUUUUUð aY€…tPh€ô$Ãçï1-$ø±YèH ç¥$€…UÌI—YÉj€Éj€€,€Usg€±I—UÌUÌ1-çïçïÃà ŽUÌ€…˜ï¥$±Yh[æ1-ô$Ûº¤Ë€¤Ë€Œa€Us±€ô$Y$ø=b½5€€,€çïÃYÕŸI—YY½5€½5€¤Ë€j7 ú—‚7 ú—‚7 €j[€½5€Éj€¤Ë€€,€˜–€˜–€˜–€s÷€±€çïÉj€Éj€Ûºô$YÉj€¤Ë€= j= I>Us ŽI—[æ=bÛºUÌô$çï1-UÌŒº½Žâ-â-˜ïUÌUÌ1- ŽÛº¤Ë€Us€,€çïÃ=b Ž$øÉj€ÛºÉj€ÛºÛº Ž7777±YBUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀H0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUTUUUUUUUUUUTUUUUU@UUUUUð a[æ[æ[æ=bI— Ž ŽYY±€˜–€˜–€˜–€½5€ô$1-ô$Éj€ÕŸ€çïÛº±€çïô$1-1-[æ1-çïÛº˜–€= jj 5+Ä|jg€¤Ë€Ûº½5€±€½5€ÕŸ€çïYY=b ŽÃçïÕŸ€±€€,€$Ÿ±²~±²~±²~±²|Us[€[€€,€€,€±€Œa€€,€€,€= = ÕŸUÌtP=b±€€,€g€0Ô0ÔUs0Ôú—€ 5$Ÿj$Ÿj= $Ÿ0ÔÛºYÃUÌI—Éj€çïUsj7 s‚7 €$Ÿg€՟ ŽYô$ÛºçïÉj€˜–€Éj€¤Ë€ÕŸ€±€±€½5€ÕŸ€Éj€±€Ûº7777±YBUFR&bÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΂UU[Þ÷½ï{Þ÷½ï{Þ÷½ñŒcÆ1ŒcÆ1ŒcÆ3œç9Îsœç9Îsœç9Îu­kZÖµ­kZÖµ­kZÖ·½ï{Þ÷½ï{Þ÷½ï{ÞÀŠ …1Е1®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUUUUUUUUUTUUUUTUUUUUUUýà`$Ÿ 5| 5g€ۺYÃÃô$Éj€Éj€çïÉj€çïO±¥$¥$€…O±1-ÃYô$Éj€±€½5€½5Y[æÉÂ%QÜ[æ€çï=bÛºs÷€ÉjO±½ŽÕøŒºhO±ý5€ú>‚+k‚+k‚¥}|jOX€Ï…Éj€½5€ÛºŒa€OX€[€¤Ë€˜–€±€½5€Ï…¤Ë€s÷€I>j 5 5~¥}|€,€€,€€,ƒ|I>s÷€OX€0Ô$Ÿ$Ÿ 5 5I>I>= g€= 0Ô~+ktP€ú>€ú>tP€€€€,îb€0Ô= j0ÔOX€OX€s÷€OX€OX€s÷€€,€Œa€˜–€Ûº Žs÷€OX€0Ô+ktPtP€ú>îb€[€j7777º‚BUFRöbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀ@"""""%UUUUffffffffffffwwwwwwwwwwwwˆˆˆˆˆˆˆˆˆˆ€Š¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥¾”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS c\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðEUUPUUUUTUUUU@UUUUDUUUUUUUUUð `j+Ä| 5$Ÿj 5Œa ŽÃYI>0Ô$Ÿ±²~±²}ú—ú—ú—€j€,€ô$=bÃYÃÛº$ø$øô$YYh1-ÛºŒa€= 57 ‚7 ‚7 ‚±²+Ä|[€½5€ÛºÉj€g€gÂh€…€çïÛº±€s÷€[€Usj 5+Ä~7 ú—‚7 €jI>[€s÷€I>Us= = 0ÔUs$Ÿg€g€s÷€[€0Ô0Ô$Ÿ 5 5+Ä|7 ‚±²|jjI>= $Ÿ 50Ô€,€Œa€½5€çïI— Ž ŽÛºô$ô$YÃŒº‚€Þ[怽5€½5€¤Ë€ÕŸ€ÕŸ$øŒºÉÃh€ô$ Ž7777€ÛBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀ$0I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»m¶Û`‹pC!Lv5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTUUUUUUUUUUUUUUUUUUUUUUUUð `˜–€Œa€±€ÕŸ€Éj€Éj€½5€Ûºô$ô$½5€¤Ë€½5€Ûº ŽÉj€±€±€½5€ÕŸ€˜–€Us0Ô+Ä}ú—ú—€ 5I>±€½5€½5€˜–€˜–€Œa€Œa€Œa€˜–€ÕŸÃI— ŽÕŸ€ÛºÃY˜–€˜–€½5€[€[€¤Ë[æÉÃÕøUÌ1-1-ô$ô$ô$çïI—=bI—€…[æI— Ž¤Ë€Us0Ô0Ô 5I>s÷$øŒº¥$Œº$ø1-Ã=b1-=btP¥$Œºh[ætP˜ï€…Œº=b$øÃô$½5€ÕŸ€ÕŸ€çïÉj€Ûº¤Ë€Éj€Éj€½5€½5€Éj€ÛºçïÕŸ€ÕŸÃ1-$øç€j+Ä}ú—‚7 ‚7 € 50Ô7777€BUFR¶bÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀ<0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@&% \0Ô ŽzÄnè ëýà3á@ŒaUÌ28ÈB@ 9ûÀReÀOX€ªæ¸ØýàI>†GY† ²&\ ‰hã`*¹€g€ÃPI—²Ä´¸Ø q°Ö \À$ŸI> Žc øPýà6î€zÛº† «˜&\ ‰h\À)2àa¨Ûº† ²&\ q°ð 3á@€,€·Y ŽW0 q°!‘À= g€ۺ·t«˜Ä´ øPã`6G[æ‚Ðdp¾hýà ®`\ÀŒaÃÜl?xû1—PZàs÷€Ï…n6ÏÞ&\ ‰h™p*¹€’|h‚ndÆO€$Ÿ9ûÀg€ç1†d q°w@I>•‰AYUÌnè?x±(ýàF0À†G Ž77771BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀP0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÛnÛ`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶6”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUU@UUUUUUUUEUUUUUUUUUUUUð a=b ŽÃ ŽÃô$ô$ÕŸ€½5€¤Ë€±€ÕŸ€ÛºÕŸ€ÕŸ€€,€€,€s÷€Éj€Éj€çïà ŽI—1-Ã Ž¤Ë€I>g€¤Ë€I>Œassú—‚7 €…€ 57 €0Ô[€Œa€˜–€Œa€€,€ÕŸ˜ï˜ï=b$ø$ø1-Y˜–€s÷€¤Ë€ÉjYI—[æ=b ŽŒa€s÷€I>€,€Œa€ÕŸY¤Ë€¤Ë€˜–€= 0Ô+Ä|$ŸjUs€,€g€¤Ë€±€ÛºÛº±€½5€±€ÕŸ€ô$Y ŽÛº$øY ŽçïÕŸ€¤Ë€s÷€I>0Ô= I>€,€Ûº[æ[æ=bÛºÛºô$ÕŸ$ø ŽÛº˜–€˜–€˜–€Œa€Œa€I>Us= 0Ô 57777€BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀh0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUEUUUUUUUUð ` 5I>€,€¤Ë€±€s÷€Œa€Œa€€,€¤Ë€ÕŸ€ÉjY ŽÃY½5€±€g€€,€€,€I> 5 5Us€,YÛºçïÕŸ€¤Ë€½5€±€¤Ë€˜–€¤Ë€Ûº1-ÕŸ ŽçïÉj€s÷€s÷€s÷€ 5 5$Ÿ$ŸŒa€¤Ë€¤Ë€±€Éj€Ûºçï¤Ë€ÛºçïÕŸ€çïÛºô$çï1-Yçï±€˜–€s÷€€,€Éj€Éj€çïYg€s÷€½5€I>0Ô= [€s÷€˜–€±€±€Éj€Éj€±€ô$[€ 5+Ä|Us½5I—$øY½5€˜–€çïÛº½5€ÕŸ€½5€ÕŸ€ÛºçïÃÃô$Éj€[€0Ô= = Œa€çï1-I—€…â-˜ï$øÉj€ÕŸ€7777€BUFR&bÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÂUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{ÀB„!B„!B„"„!B„!B„!cÆ1ŒcÆ1ŒcÆ1Œ„!B„!B„!@Š×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUTPUUUUUUUUUUUUð `Ûº¤Ë€s÷€[€±Y˜–€$Ÿ0Ôj±²+Ä~±²~7 €…ƒ+Ä|j= ˜–€[€g€g€I>I>g€s÷€Éj€ÕŸ€çï€,€I>Us[€Us$Ÿ 5j 5jg€¤Ë€¤Ë€Œa€˜–€˜–€g€g€[€0Ô= ±€çï=b½5€€,€I>$Ÿ±²| 5+Ä+Ä|ŒaUÌI—Ûº˜–€˜–€Œa€€,€Œa€¤Ë€Éj€ô$±€[€Usú—€Œa€Œa€…€Œa€Œa€Œa€…€= ˜–€Œa€g€I>I>I>= j0Ô0Ô0Ô= 0Ôj 5 5j+Ä~7 ‚±²+Ä+Ä|j0Ô= [€= I>0Ô˜–€[€˜–Y1-Ã1- Ž7777º‚BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ý¶Û`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡,kŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUPUUUTUUUUUð `çïI> 5 50ÔŒaYYYÕŸ ŽÕŸ€Éj=b€,€€,€˜–€½5€½5€½5€0ÔŒº‚=»½ŽhhI— Ž ŽYÕŸÃ1- ŽÕŸ€±€Éj€Éj€s÷€s÷€[€±€±€½5€ÕŸ Ž1-1-=bý5€g€˜–€ô$=b1-tPh$øÕŸ$øÛº$øÉj€Us= Us€,€UsjI>j7 ‚±²}ú—ƒ+Ä|$ŸUsUs= [€s÷€I>[€g€Œa€˜–€= 0Ô$Ÿ0Ôj$Ÿ±²+Ä}ú—‚±²| 5[€ÕŸ€çïÕŸ€Éj€Éj€Ûº±€¤Ë€¤Ë€˜–€½5€˜–€Œa€€,€¤Ë€˜–€g€= +Ä+Ä}€…€…‚7 €jI>Œa€7777 ‚BUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î,0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUU@UUUUUUUUUUUUUTUUUUUUUUUð `Œa€˜–€¤Ë€Œa€€,€€,€s÷€€,€[€UsI>˜–€Éj€s÷€€,€Us= Us0Ô±²|jj+Ä~±²+Ä~±²~±²+Ä| 5$Ÿ0Ô˜–€¤Ë€˜–€€,€€,€= $Ÿ 5 5 5j0Ôjj 5 5j 5$Ÿ0Ô0ÔUsUs0Ô0Ô0ÔUss÷€$Ÿ$Ÿ0Ô˜–€½5€Œa€€,€s÷€[€Œa€ÉjÃŒa€½5€½5€Éj€€,€jUs7 sú—ú—‚±²|j˜–1-ÃYçïÛº½5€ÕŸ€Ûºçïçïçïô$ÃhI—=b½5€Us= [€±€çïYÛº$øh$ø$øçïÉj€¤Ë€±€Éj€ÕŸ€7777 ‚BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶à‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„­sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUTUUUUUTUUUUUUUUUUUUUUUUð a=bYYUÌ$øçï Žg€j 57 ‚±²+Ä|Us˜–€ÕŸ€ÕŸ€±€½5€Éj€Ûº½5€Éj€½5€Ûº½5€Œa€Us[€€,€±€Œa€I>= 5±²|UsÛºô$Ãçï Ž=bÉjÃI— Ž$øô$Ã[æUÌ$øÛºs÷€I>Usj±²~7 €0Ô= j 5jj 5$ŸI>g€s÷€ 5 5j0ÔI>g€[€s÷€Us0Ô€,€€,€Œa€ÕŸ€ô$Ãçïçï½5€Éj€½5€I>Œa€çïçï±$øÉÃ½Ž½ŽhI—1-Yçïçï$ø=bUÌUÌçn€ÕŸ€ÕŸ€ÛºÉj€s÷€€,€˜–€¤Ë€Œa€[€[€s÷€[€7777 ‚BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎX0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUPUAUUUUýà`I>= I>0Ô[€¤Ë€Ï… ŽY˜–€s÷€±€Ï…ô$½5€Œa€s÷€OX€s÷€ô$1-$ø˜–€js÷€$Ÿ0ÔÛº1-O±Ã ŽÏ…˜–€¤Ë€Ûºçï[€€,€¤Ë€½5YÃYô$Ûº±€g€OX€OX€$Ÿg€±€Ûº$øÛºYçïÛºçïÉj€Œa€s÷€g€[€€,€˜–€Ûº½5€s÷€¤Ë€€,€ 5 5$Ÿ= Œa€ÉjÃÛºOX€[€I>[€$Ÿ$Ÿ[€[€= $ŸÏ…Ï…ÛºÃs÷€¤Ë€˜–€j+k€ú>‚+k‚¥}~¥}~¥}|jI>I> 5+kƒ| 50ÔOX€¤Ë€ŒaO±1-$ø½5€˜–€s÷€g€Œa€½5€…h1-7777 ‚BUFR&bÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎUUUUUUUUUU]kZÖµ­kZÖµ½ï{Þ÷½ï{Þ÷½ï{Þ÷Îsœç9Îsœç9Îsœç9Þ÷½ï{Þ÷½ï{Þ÷½ïz„!B„!BŠ•-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUTUUUUPUUUUUUUUUð `½5€½5€Œa€ÕŸ€Éj€½5€½5€½5€Éj€Œa€¤Ë€€,YÉjYô$Ãô$ô$ÕŸ€ô$Ãô$Éj€ÕŸ€¤Ë€±€˜–€±€€,€Éj€ÛºçïÛº1-=bÛºs÷€0Ô= [€= s÷€ÛºÛº½5€€,€s÷€g€= $Ÿ0Ô= Us= g€[€g€[€s÷€s÷€$Ÿ7 ‚±²}€…s€…€Us±€Œa€Us[€s÷€s÷€€,€¤Ë€˜–€¤Ë€€,€$Ÿj 5 5 5±²}ú—ƒ+Ä|$Ÿ 5[€çï$øYô$ÕŸ€±€¤Ë€Éj€½5€çï ŽÃô$çïÛº€,€[€0Ô 5$ŸI>¤Ë€Éj€Œa€s÷€s÷€g€Us[€[€s÷€= €,€7777º‚BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$–Ûm¶Ûm¶Ûm»`‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Ж5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUP@EUUUUUUUEUUUUPUUUUUUUUTð `g€I>€,€±€Us€,ƒ+Ä+Ä~±²}€…€Œa€…s€…‚±²+Ä|ú—‚±²+Ä|+Ä|±²~±²|$Ÿ±€±€çïô$YY½5€Éj€±€Œa€[€s÷€ 5j$ŸI>j$Ÿ0Ô$Ÿ0Ô$Ÿ0Ôg€ô$çï¤Ë€Œa€g€$Ÿ±²| 5I>Yô$Ûº½5€˜–€Œa€Œa€s÷€s÷€Us[€±€ô$ô$ÕŸ€Éj€ÕŸ€jú—s‚7 sú—€= ¤Ë€½5€s÷€0ÔI>0Ô[€±€½5€Œa€s÷€Us€,€I>jú—s€…€…sú—€s÷€€,€[€[€g€UsUsI>I>UsUs[€I>I>[€[€Usj±²|7777€BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@ 0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUT@UUUUUUUUUUð `j= [€g€¤Ë€Œa€€,€g€Usg€±€ô$1-=b[æ$ø$ø=bÉjÃYÛº=bYÉj€ÛºŒa€½5YÕŸ€˜–€Œa€€,€[€g€UsUs$ŸI>I>€,€€,€½5€€,€±€¤Ë€€,€0Ô7 €…ƒ+Ä|±²~±²| 50ÔI>Us$Ÿ±²~7 ‚7 ú—‚±²|+Ä~7 s€O€Os€Œas€…€$Ÿs÷€Œa€¤Ë€I>I>UsI>= = I>Œa€= $Ÿ+Ä~±²}ú—€…€Œasú—ssú—€I>±€çïÕŸ€±€Éj€ÕŸ€ÛºÛºY ŽÃYÃô$ÃY½5 ŽçïŒa€g€ 5= I>±€ÕŸ€ÛºÛºÕŸ€7777€BUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@40’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUEPð `½5€Œa€˜–€±€½5€Éj€ÕŸ€½5€Éj€¤Ë€€,€Us= 0Ô[€$Ÿ$Ÿ$Ÿ€,€Œa€¤Ë€Œa€€,€Œa€€,€çïô$ÉjÃ$øg€I>g€½5€±€= 50Ô 5 50ÔŒa€ÕŸYçïô$çïg€0Ôj= = I>$Ÿ$ŸI>½5€±€ÛºŒa€g€€,€Us0Ôj[€˜–€Éj€çïÛº±€I> 5 5±²|±²~±²|j= [€$Ÿ 5 5I>0Ô 5 5 5+Ä}€…ú—ú—ú—ú—ú—ú—ú—ú—ú—‚±²+Ä|$Ÿ 5jj$Ÿ0Ôg€ۺ[怅€ÕŸ€jj+Ä| 5$Ÿ 5ú—‚±²|7777€BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@H0’I$’I$’I)$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT·>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUTUUUUUUUUU@UUUUUUUUUUU@ð `= = s÷ Ž ç½5€±€Éjà Žh‚ ç€Þ‚ôÖh€Ûº$Ÿj$Ÿ= 0Ô0Ôs÷€$Ÿ 5+Ä}ú—€…ƒ+Ä}ú—ú—ƒ+Ä|g Ž ŽÛºY ŽÛº€,€Ûºô$çïÕŸ Žô$I>$Ÿj0ÔŒa€s÷€g€s÷€˜–€Ûº½5$øÕŸ€€,€€,€Œa€s÷€[€€,€Œa€˜–€€,€0ÔUsI>+Ä~±²}€…ƒ+Ä|$ŸI>± ŽÕŸ€€, Ž ŽÉj€çïô$1-ŒºŒº[æ1-ô$Éj€˜–€˜–€Œa€[€Us$Ÿ 5$Ÿg€Us€,€g€Œa€½5€±€˜–€çïÉj€½5€¤Ë€€,€g€€,€¤Ë€˜–€€,€$Ÿ$Ÿ±²}ú—€…€7777€BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@`0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUPUUUUPUUUUUUUUUUQUUUð a€…‚7 ‚7 ‚±²|j0Ô 5j 5$Ÿ 50Ô= jjj7 ‚±²}€…s€…€…ú—‚±²~±²~±²| 5j 5 5 5[€g€0Ô 5±²~7 ú—ú—‚7 € 5g€Œa€¤Ë€Œa€˜–€ÕŸ€±€Ûº½5€˜–€s÷€Usg€0Ô0ÔI>j+Ä~±²|jI>Œa€˜–€±€Œa€[€g€UsUs[€0Ôs÷Y=bô$¤Ë€€,€€,€€,€Us0Ôj+Ä+Ä}ú—‚±²|Us€,€Œa€€,€Œa€s÷€= g€½5€ÕŸ€Éj ޽5€¤ËYg€0Ô0Ô+Ä| 5 5€,€¤Ë€˜–€[€= $Ÿ[€¤Ë€7777€BUFR&bÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎBUUUUUUUUUUUUUUUUU^sœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷¾÷½ï{Þ÷½ï{Þ÷½ï{ÀB„!B„!B„"„!B„!B„ Š×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS c\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUD@UUUUUUUUUUUUUUUUUUð `±€= ˜–€ÕŸ€çïçïYh‚ ç²ÉÃÉÃŒºI—ÃÛº˜–€½5€g€˜–€ÕŸ€s÷€Us0Ô$Ÿ0Ô0Ô±²|+Ä|+Ä~±²}€…‚7 €…s€Œa€…‚7 €j= I>I>= UsI>I>= [€˜–€¤Ë€ÉjY Žçïs÷€= 0Ô$ŸUsg€˜–€ÕŸÃÕŸ€€,€[€s÷€I>Œa€jUs˜–€Œa€€,€€,€±€Éj€g€I> 5+Ä|€…€…ú—€$ŸI>[€g€s÷€s÷€ÕŸ€çïÕŸ€˜–€[€Us= = Ûº ŽÃÉj€j±²~7 ‚±²|s÷Y=bô$±€Œa€±€ô$$ø ŽY[€I>= I>j7777º‚BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀ 0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUQUUUUUUUUUUUTUUQEUUUUð `jj 50ÔI>g€g€UsŒa€g€g€= j+Ä|j$Ÿs÷€= $Ÿg€±€gƒ+Ä}ú—‚7 s€…‚7 €$Ÿ0Ôjj$Ÿ0Ô$ŸUs0Ô$Ÿ0ÔUs$Ÿj$ŸUsI>= j 5±²| 5+Ä|$Ÿ 50Ô= I>¤Ë€ô$çïÕŸ€Œa€˜–€€,€˜–€çï± Žô$€,€= jú—ú—ú—€0Ô$Ÿjj= = 5j 5 5±²|±²|0Ô±²|±²+Ä+Ä|0ÔUsŒa€½5€½5€˜–€Œa€g€Œa€˜–€Œa€s÷€˜–€s÷€[€˜–€€,€0Ôj+Ä}s‚7 ú—ú—‚7 ƒ+Ä|$Ÿ7777 ‚BUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀$0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTUUUUU@UUUUUUUUUUUUUUUUEUUð `Us= $Ÿ0Ô$Ÿj 5jj 5+Ä|[€j= ±²}ú—‚±²~±²}€…€ 5$ŸŒa€±€˜–€[€g€0Ô= Us±€s÷€¤Ë€½5€˜–€½5€ÕŸ€±€g€ 57 ƒ+Ä}ú—ú—€ 5I>I>Œa€s÷€¤Ë€Éj€½5€¤Ë€€,€˜–€¤Ë€±€˜–€Œa€ÉjÃô$ÕŸ€¤Ë€[€I>0Ô+Ä|0ÔŒa€½5€¤Ë€Œa€s÷€˜–€s÷€Œa€˜–€€,€[€€,€¤Ë€½5€ÛºYI—$øÃÛº[€Œa€Œa€$Ÿ0Ô$Ÿ$Ÿ$Ÿ0Ô0Ô$ŸI>g€I>= Us[€Usg€¤Ë€Éj€±€¤Ë€€,€[€0Ô±²|0Ô0ÔjI>Œa€˜–€[€[€˜–€7777 ‚BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀80I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Ûm¶Ûm¶Ûm·`ŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!N„©l|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `Éj€çïÛºs÷€I>Œa€˜–€Usj±²|±²|0Ô˜–€çïçïÛº=b1-ô$Ûº½5€ÛºY[æ Ž½5€½5€Éj€Éj€ÕŸ€€,€I>I>0Ô[€g€¤Ë€Éj€ô$ÕŸ€ÕŸ€€,€¤Ë€çïô$ÛºÛºçïÕŸ€Œa€¤Ë$ø±Yh€˜–€$Ÿg€[€Œa€€,€ÛºÃ Ž ŽÕŸ€ÕŸ€Œa€Œa€s÷€€,€Éj€¤Ë€€,€€,€˜–€˜–€çï¤Ë€˜–€I>0Ôj 50Ôg€Éj€¤Ë€˜–€s÷€Œa€g€€,€s÷€€,€Œa€Œa€¤Ë€€,€s÷€[€= 0Ôjj 5jUss÷€Us0Ô0Ô0Ô0ÔUsUs±€ÕŸ€€,€s÷€ÕŸ€˜–€¤Ë€¤Ë€¤Ë€s÷€Ûº7777 ‚BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀P0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUEPTUUUUTUUUUUUUUUUUUð `˜–€jI>ÕŸ€ÛºÉjI—=b=b[æ€ô$g€= ±²|jj+Ä~±²~±²~±²+Ä+Ä~±²|g€Us 5±²~7 ú—‚7 ‚7 ƒ+Ä~±²+Ä+Ä~±²~7 ‚±²~±²~±²+Ä|$Ÿ0Ô$Ÿ0Ô= +Ä+Ä| 5$Ÿ$Ÿj$Ÿ= 0Ô0Ô= [€$Ÿ= Usg€UsI>gÂ Ž˜–€Éj€g€±²~7 ‚±²|[€˜–€s÷€I>= $Ÿ= = = = [€€,€½5€Éj€½5€¤Ë€s÷€[€0Ô±²+Ä|0Ôg€Œa€s÷€s÷€Uss÷€€,€˜–€˜–€Œa€Œa€s÷€s÷€± ޱ€ÕŸ€±€s÷€I>Us€,€g€Uss÷€g€g€[€7777 ‚BUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀d0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUAUUUUUUUUUUUð `0ÔI>= Us€,€g€€,€±=b$ø ŽÕŸ€˜–€j 50Ô 5 50Ô€,€½5€Œa€˜–€˜–€˜–€˜–€¤Ë€Œa€±€½5€¤Ë€½5€˜–€˜–€g€0Ôj7 ‚±²|j$Ÿ[€= j[€˜–€˜–€g€g€s÷€g€g€g€Éj€±€˜–€I>I>€,€Œa€[€0Ôj 5 5±²~±²~±²~±²|j+Ä~±²|+Ä+Ä~±²+Ä|= = 57 ‚7 ‚±²~±²|$ŸUsg€€,€€,€s÷€Usg€s÷€g€g€¤Ë€€,€g€[€Éj€˜–€[€$Ÿ[€€,€€,€[€s÷€¤Ë€±€Ûº¤Ë€½5€½5€½5€ÕŸ€ÕŸ€½5€±€s÷€¤Ë€7777 ‚BUFR&bÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΂UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU^÷ B„!B„!B„"„!B„!B„!CÆ1ŒcÆ1ŒcÆ1Œd!B„!B„!B…)JP‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUP@UUUUUUUUUUUUUUUUUTUUPð `Œa€±€Œa€Us¤Ë€˜–€UsI>¤Ë€±Y±€[€˜–€½5€€,€UsUsg€˜–€s÷€±€g€0Ô= $Ÿ+Ä~7 € 5±²}ú—ƒ+Ä|I>€,€±€±€½5€Œa€g€˜–€˜–€Éj€½5€Ûº¤Ë€€,€Œa€Œa€g€€,€0Ôs÷€çïI>I>g€çïI—ô$çïÃçïçïà ŽÕŸ€Ûº½5€±€˜–€¤Ë€ÛºŒa€Œa€[€j= 0Ô$Ÿ$Ÿ$Ÿ0ÔUsUs[€g€[€g€s÷€[€g€Us[€˜–€s÷€UsI>0Ô 5I>$Ÿ7 €0ÔUsj±²+Ä|+Ä~±²+Ä+Ä| 5= = j+Ä}€…‚±²}ss‚7 €7777º‚BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀ0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUUUUQUUUUTUUUUUUUUUUTTð `$ŸŒa€±€¤Ë€Œa€Œa€g€¤Ë€½5€€,€= 5j 5 5+Ä}ú—ú—ssú—€…ú—‚7 €j¤Ë€çï½5€½5€½5€˜–€±€˜–€Œa€g€Œa€[€I>Us[€g€g€I>= j 5±²| 50Ôs÷€˜–€Œa€Œa€s÷€[€= UsI>s÷€ÕŸ€˜–€[€Us= 0Ô= I>+Ä+Ä}ú—ú—€= 0ÔI>$Ÿ0Ô0ÔUss÷€s÷€˜–€˜–€Œa€g€g€[€s÷€€,€˜–€˜–€€,€g€I>I>I>±€ô$ ŽÛº¤Ë€˜–€€,€€,€€,€€,€±€ÕŸ€s÷€I>Us0Ô= I>j±²~±²}ú—€…‚±²~±²|j 5+Ä|$Ÿ$Ÿ+Ä|7777Ä|BUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀ,0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS c\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUEUUUEUUUUUUUUUUUð ` 50ÔŒa€¤Ë€€,€I>$Ÿ$ŸI>g€I>+Ä~7 €…€…‚7 €$Ÿ 5 5j+Ä~±²}ú—€ú—‚7 ú—ú—ú—ú—€…ú—‚7 ú—ú—€ 5$Ÿj0Ô0Ô0ÔUs$Ÿ 5 5 5 5+Ä| 5+Ä~±²}ú—s€…ss€…ƒ+Ä|j[€I>j= $Ÿ= I>I>UsI>Us0ÔjI> 5±²|0Ô= I>[€[€UsUs= 0Ô[€s÷€€,€s÷€= I>˜–€Œa€€,€Us= $Ÿ0Ô€,€s÷€s÷€s÷€˜–€Ûºs÷€˜–€€,€€,€½5€€,€[€±€Ûºô$ÕŸÃI—ô$Y7777Ä|BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀ@0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUTQPUUUUUUUUPUUUUUUUUU@ð `Ûº€,€I>jjI>Œa€½5€½5€˜–€¤Ë€g€[€I>0Ô$Ÿ0Ô$Ÿ 5 5jjUsI>[€0Ô= +Ä+Ä| 5$Ÿj+Ä| 5 5+Ä+Ä| 5j 5jI>0Ôs÷€±€UsÉj€Œa€I>$ŸI>I>j= jI>= 0Ô0Ôj0Ô= I>Uss÷€Œa€g€j±²~±²~±²|j[€s÷€Œa€g€UsUsUsI>€,€s÷€±€€,€0Ô€,€˜–€½5€Éj€±€Œa€I>$Ÿ 5ú—ú—€I>g€[€Us= 0Ôj$Ÿ= I>0Ôg€I>j$Ÿ[€Us[€$Ÿú—‚±²~7 ‚7 € 50ÔI>7777Ä|BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀX0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUU@UUUUUUUUUUUUUUUUTUUð `s÷€˜–€g€s÷€[€˜–€˜–€g€€,€ÕŸ€ÕŸ€= = = [€0Ô 57 ‚7 €…‚7 €= €,€½5€Œa€= = I>= I>I>€,€[€Us0ÔUs0Ô= = 5+Ä+Ä~±²+Ä|= s÷€€,€Éj€s÷€[€UsUsUsg€±€[€€,€€,€[€€,€½5€ÕŸ€ÛºYô$ÛºÉj€˜–€˜–€¤Ë€½5€€,€I>Us= UsUss÷€[€s÷€½5€±€ÕŸ€±1-â-½ŽŒº[æ ŽÕŸ€Œa€I>Us€,€g€˜–€Us$Ÿ= = $ŸUs= s÷€€,€s÷€Œa ŽÉj€±€¤Ë€[€ 5±²+Ä|g€˜–€½5€½5€g€UsI>Us˜–€¤Ë€7777Ä|BUFR&bÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÂUUUUUU]kZÖµ­o{Þ÷½ï{Þ÷½ï{Þ÷¾sœç9Îsœç9Îsœç9Î÷½ï{Þ÷½ï{Þ÷½ï{ß{Þ÷½ï{Þ÷½ï{Þ÷½àŠøFS¥mpC!Lt%LkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUEUUUUTUUUUUTUUUUUUUUUUUPPð `˜–€¤Ë€UsUs€,€½5€s÷€$Ÿ+Ä|[€[€0Ô= €,€˜–€Œa€s÷€€,€€,€Œa€€,€¤Ë€ÛºYÛºÕŸ€çïÕŸ€Éj€$Ÿ±²|I>Œa€UsI>UsI>g€Œa€g€Usg€[€I>g€g€¤Ë€ô$Éj€€,€g€g€s÷€= +Ä~±²| 5 50ÔUsUs= = j= = UsŒa€€,€g€s÷€g€[€UsUs$Ÿ 5+Ä| 57 ú—‚±²|jUsŒa€g€€,€Œa€Œa€Œa€Œa€½5€¤Ë€€,€€,€±€çïÕŸ€ô$ÛºÛº˜–€¤Ë€€,€€,€I>0Ô 5= I>$Ÿ+Ä~±²~7 ƒ+Ä| 5±²| 5±²+Ä+Ä| 57 €7777º‚BUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUUUUUUTUUUUUUUUUUUUUUUUUð b±²| 5 5j7 €j+Ä}€…€…‚7 € 50Ôj+Ä|g€0Ôj= Us0ÔUs$Ÿ$Ÿg€€,€0Ô= ÕŸYY¤Ë€g€±€€,€[€UsUs€,€Œa€[€= = 5$Ÿ±²+Ä|j±²+Ä| 5g€€,€g€I>0Ô= j$Ÿ0Ô$Ÿ= [€I>I>I>0Ô$Ÿ 5+Ä| 5±²~±²+Ä| 5= g€[€[€UsUsI>[€Usg€¤Ë€Œa€s÷€Œa€Éj€Éj€ô$I>0ÔŒa€Œa€[€I>[€g€s÷€s÷€€,€UsUs[€[€[€[€g€[€Usg€s÷€€,€[€0ÔI>[€s÷€Œa€Œa€€,€g€s÷€7777ÔBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„ª2+k€" c¡*[çÂ2+k€" c¡+c\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUPUUUUUUUUUUUUUUýà`±€Œa€¤Ë€˜–€Œa€I>g€s÷€€,€s÷€[€ÉjO±=bŒa€0Ôj$Ÿ[€Œa€s÷€[€g€g€OX€OX€OX€= I>OX€= I>[€Œa€= j}îbƒ}tP€€€€,€ú>îbtP‚+k‚¥}}îb€ú>€ú>€€,€ú>tP€ú>îbîb‚+k‚¥}}îbtPtP‚+kîbtPtP‚¥}| 5= = [€$Ÿ˜–€s÷€Ûº˜ï±Y1-±€±€ô$=b[æ1-Yçï ŽÃô$¤Ë€€,€€,€±€˜–€±€Éj€Œa€Œa€Éjh€¤Ë€±€±€I>= $Ÿ= s÷€€,€[€I>s÷€= j= 0ÔI>I>[€[€OX€$Ÿ 5j7777ÔBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î00I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@UUUUPUUUUUUUUUUUUUUDUUUUUUð `±²+Ä~7 ‚±²|0ÔUs€,€I>= I>UsI>0ÔI>= I>s÷€[€Uss÷€s÷€UsI> 5+Ä~7 ƒ+Ä|j= Us½5€˜–€¤Ë€Œa€€,€I>= [€UsI>UsI>[€˜–€Œa€[€Us 5 5= 7 €I>= UsUs[€I>s÷€g€[€[€= UsI>UsYô$ Ž1-$ø ŽÉj€˜–€±€±€Œa€€,€s÷€€,€[€0Ô+Ä| 5$Ÿ0ÔUss÷€Œa€Éj€= +Ä|7 ‚7 ƒ+Ä|js÷€€,€I>0ÔI>Us$Ÿ= ˜–€Œa€[€[€[€s÷€Œa€¤Ë€˜–€˜–€Us€,€I>$Ÿ 5s÷€ÕŸ€7777ÔBUFRæbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎH0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUU@UUUUTUUUUUUUUð `ÕŸ€€,€˜–€˜–€s÷€g€¤Ë€½5€ô$1-$øÕŸ€çïÛºçï½5€±€çï ŽÕŸ€Éj€½5€ÕŸ$ø[æ[æ€çïŒa€±€Œa€¤Ë€€,€g€¤Ë€€,€½5€ÕŸ€g€I>= I> 5s÷€jjUs€,€¤Ë€˜–€I>UsUs= 0Ô0Ô= 0ÔUsUsUsI> 5I>0Ôú—ƒ+Ä}ú—‚7 ú—€= s÷€€,€€,€¤Ë€g€Us€,€s÷€g€g€g€= I>= j$Ÿjj±²}€…‚7 €I>I>0Ô0Ô$Ÿ0Ô0Ô= g€UsI>I>= 0Ô€,€s÷€I>s÷€ÛºŒa€ÕŸ€½5€˜–€Us$Ÿ= €,€Usj$Ÿ[€0Ô[€= 7777ÔBUFRöbÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î\@""$DDDDDDUUUUUUUUUUUUffffffffffffwwwwwwwwwwwwˆˆ€ŠøFS¥mpC!Lt%Kc\øFS¥mpC"Ø×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUUUUUUUUUUUUUUTT@ð `0Ô 5 5$Ÿg€ 5 5+Ä}s€Osssú—€s÷€½5€ÕŸ€±€ÛºŒa€¤Ë€ÕŸ€Ûº½5€çïÕŸ€±€˜–€ÉjY ŽÕŸ€s÷€= = 5[€s÷€˜–€€,€˜–€Œa€çïÕŸ€¤Ë€±€çïÉj€Œa€˜–€g€g€s÷€€,€€,€€,€[€Éj€Éj€ô$Y½5€¤Ë€€,€Œa€Éj€çï Žô$Éj€ô$ÃY ŽYÕŸ€¤Ë€g€s÷€Œa€Œa€s÷€˜–€±€±€s÷€s÷€Œa€½5€±€½5€Éj€ÕŸ€Ûºô$YÕŸ€½5€½5€Œa€Œa€s÷€[ƒ+Ä| 5+Ä}ú—ƒ+Ä|±²}€…ú—‚7 ú—‚±²| 5 5+Ä}ú—‚7 ‚7 ú—€ú—ú—ú—€7777~±BUFR&bÿ« fÎ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎUUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷½ï{ÀB„!B„!B„"„!B„!B„!CÆ1ŒcÆ1ŒcÆ1Œd!B„!@ŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@UUUUUUUUUUPUUUUUUUUUUUTPUUð aú—€ 5±²}€…€…ú—€…€…€…€…‚7 ‚±²~±²~7 ‚7 ƒ+Ä+Ä~7 ‚7 ‚±²|±²~±²+Ä|= [€I>0Ô= I>½5I—UÌ[æ˜ïÃUÌÕø±Y¥$€…I—1-ô$Éj€½5€˜–€¤Ë€ô$YÛºÛºÛºŒa€˜–€±€Ûº$øÛº½5$ø=bI—I—gƒ+Ä+Ä|Ûº= $Ÿ¤Ë€çï[怅UÌçïÛºÕŸ€Éj€½5€ÛºY½5€ÕŸtPŒºUÌÃÛº$ø$øô$ÕŸ€¤Ë€¤Ë€½5€½5€Œa€±€Ûº˜–€€,€I>g€s÷€€,€˜–€ÕŸYÉj€0Ô 5±²|j7 ‚7 €$Ÿ˜–€Éj$øÃÃ1-I—7777º‚BUFRbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!²LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@PB„!B„!B„"„!Bsœç9ï{Þ÷½ï{Þ÷½ï{Þ÷¾„!B„!B1ŒcÆ1ŒcÆ1ŒcÊR”¥)JR”¥ Š×>”é[\ÈS RØ×>”é[\ÈS+k€" c¡*[çÂ2+k€" c¡*[øC!Lt%Kc\øFS¥mpC!Lt%Kc^Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUU@@UUUUUTUTUUUU@UUUUUð ah[æ[æ[æÃ[æUÌ=b$ø Ž Ž$øÛº½5€½5€s÷€˜–€[€= 0Ô 5j 5 5$Ÿ0Ô 5$Ÿ0Ôj 5+Ä+Ä~±²|+Ä}ú—ú—€$Ÿg€¤Ë€€,€¤Ë€¤Ë€¤Ë€±€Œa€˜–€±€¤Ë€g€[€[€Usg€€,€˜–€g€$Ÿ= ±²~±²~7 ‚7 ‚±²|jgÂÃ$ø€,€UsI>±²~±²~±²~7 €UsŒa€ÉjÃ[怌a€$Ÿ= ½5€g€I>Usg€g€[€0Ô 5±²~±²~±²|0ÔÉj€Ûº= Uss÷€[€Usjj7 ú—ƒ+Ä~7 ƒ+Ä| 50Ô[€€,€s÷€= [€Usj$Ÿ= 7777$ŸBUFR¶bÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î@\0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ð‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]1-1†Ä´Æw@6î€^šÀg€ªæn6† Ð€B@9ûÀ¤ËYÏÞÜlW0 ®`ýà9ûÀ¤Ë«?28dpB@ýà6î€s÷€½5ò«˜|(™pýàLK@Ûº’ÕôÖÄ´ L¸ )2àReÀÛº²Ä´ @ÜÈà™pýà9ûÀ= ’|UÌ$ø 'À*¹€¤Ë·tnèÝÐB@#`5gà’|I—bZc¾dpÈàýà,@ F0À[€ªæn6†  @“à 'ÀO€= ’|n6Ÿ¼Èð @@˜–’ÕddpÈর,@ ReÀ¤Ë«?bZIð @~ð,@ zÓ.õˆ L¸Ð&% ReÀº(Ahƒ1ß n ®`E&% I>^šÀ€,€7777UsBUFR&bÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎBUUUUUUUUUUUUUUUUUUUU^sœç9Îsœç9Îsœç9Î÷½ï{Þ÷½ï{Þ÷½ï{Є!B„!B„!BB„!B„!B„!ŒcÆ0Šˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUPUUUUUUUUUU@ð `UsŒa€[€I>± ŽI—â-‚ çô}¥$Œº[怌a€s÷€Œa€ÕŸ€Ûº=b ޽5€€,€Usj 5jj= = [€€,€g€[€Us= = [€g€˜–€ô$ô$çïÛºç€s÷€I>±²|+Ä}ú—‚7 ƒ+Ä|$ŸI>I>0ÔUsUss÷€= 0Ô[€Œa€€,€€,€I>0Ôj±²~7 ‚7 ƒ+Ä~7 ‚7 ‚±²|0Ô= [€s÷€€,€g€˜–€Œa€¤Ë€˜–€ô$¤ËYÃÛº˜–€Œa€¤Ë€[€I>€,€˜–€¤Ë€˜–€Éj€Éj€Éj€Éj€ÛºçïÕŸ€ÕŸ€ÛºÛºÉj ŽÃçïÕŸ€€,€= = $Ÿ 5+Ä}ú—€…ú—‚7 € 57777º‚BUFRæbÿ« fÎ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀0I$’I$’I$”’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lk¡N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUTUUUUPUUUPUUUUUAUUUUUUUUUýà`j 5|0Ô= $Ÿ0Ô0Ô0Ô$Ÿj$Ÿ0Ô+k‚¥}~¥}|jŒa€Ï…ۺυçï ޽5€[€I>= g€¤Ë€Éj€¤Ë€s÷€I>$Ÿ+ktPtP‚+kîbtPîbƒ|$Ÿ[€[€g€Œa€˜–€I>OX€0ÔI>½5ÃY½5€0Ô 5+k‚+k‚¥}}tP‚+kƒ|s÷€ÛºYô$Ï…Ï…½5€˜–€Ï…½5€˜–€½5€€,€OX€= g€s÷€OX€I>= 5¥}|[€¤Ë€çïçï¤Ë€Œa€Œa€Œa€g€[€Œa€½5€€,€Ï…Éj€½5ý5€ÛºÏ…$ø½5€Ï…çïŒa€çïI—1-ô$±€±€½5€± Ž$øÃ7777ºBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀$0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUDUUPUUUUUUUUUU@UUUUð a Žçï½5€ÕŸ€Ûº±€[€g€[€0Ô0Ôj0Ô= I>€,€s÷€Œa€€,€g€Œa€Œa€s÷€€,€˜–€Éj€˜–€g€¤ËY¤Ë€j= +Ä|7 ú—ƒ+Ä|±²~±²|+Ä+Ä| 5I>= ±€g€s÷€$Ÿs€Œas€Œa€Œa‚7 € 5˜–€ÕŸ€½5€g€˜–€€,€s÷€Œa€Œa€¤Ë€ô$Y½5Y Žô$ ŽÃÛº€,€Us= $Ÿg€ô$$ø½5€Us[€g€g€[€s÷€s÷€˜–€¤Ë€Œa€s÷€I>j±²}ú—ú—‚±²}s€Œa€…ƒ+Ä|Us€,€Éj€½5€˜–€s÷€[€g€€,€ÕŸ Žô$$ø$øUÌ1-[怌a€€,€7777ºBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀<0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUPUUUUUUUUUTUUUUUUUUð `Us= 0Ô[€½5Y Ž ŽÉj€Œa€[€= I>€, Ž1-UÌI—[æUÌŒºUÌ ŽYô$ÕŸ€±€±€±€Éj€çïÉj€¤Ë€±€Œa€€,€s÷€I>[€0Ô[€I>j= 0Ôj7 ú—€…€Œa€Œaú—€jI>g€[€jj$Ÿ 5±²+Ä|= Us0Ô$Ÿ0Ô[€Œa€€,€[€I>[€€,€[€Uss÷€¤Ë€Œa€g€UsjUs0ÔI>UsÕŸ€çïÛºYÉj€Éj€€,€I>+Ä|= ˜–€çïYYÉj€s÷€I>I>Œa€Œa€= €,€±€¤Ë€ô$çïçïô$½5€±€±€I> 5Us½5€ÕŸ$øtP€7777ºBUFRæbÿ« fÎ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀P0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUUUUPUUU@UUUUUUUUUTð a ޽5€½5€Éj€Éj€Éj€çïô$½5€€,€Us0Ô$Ÿs€Œas€Œa€Œa€…€ 5$Ÿg€g€s÷€Us[€= = [€g€¤Ë=b½5€Œa€UsUs[ƒ+Ä}€…€…€Œa€O€…‚±²|$Ÿs÷€Œa€[€[€€,€¤Ë€Ûº€,€¤Ë€ÕŸ€[€Us 5 57 €…€Os€Œa€Œa€Œa€g€ô$½5€¤Ë€Œa€Uss÷€ÕŸŒºI—hh€½5€ÛºÛº¤Ë€±€ÕŸ€ÕŸØ–€g€[€[€I>I>[€UsI>= I>g€0Ô˜–€¤Ë€¤Ë€Us0Ô+Ä~7 ú—€…s€…€Œa€O€O€Œasú—€…€…‚±²~±²|+Ä+Ä|j= 7777ºBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΀d0I$’I$’I$¤’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹N•µÀ …1Е-sáN•µÀ …1Е-®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUU@UUUPUUUPUUU@UUUUUð `jI>UsUs= 0Ô$Ÿ 5±²}ú—€…‚7 €ŒaYhY˜–€€,€±€ÕŸ€Éj$øÃ1-I—1-YÉj€˜–€s÷€I> 57 ú—sú—€ 5Usg€s÷€I>g€g€s÷€Œa€[€Œa€Œa€[€UsŒa€g€ 5ú—ú—s€Œas€…ƒ+Ä|I>g€= = 0Ô$Ÿ0Ô= 0ÔUsUsUsI>Œa€g€0Ôj+Ä}sss€…‚7 ƒ+Ä|= g€= 5 5$Ÿ 5= 0ԤˀÉj€±€s÷€Œa€g€±²}€…€…€Œas€…€[€s÷€çïÉj€˜–€¤Ë€¤Ë€¤Ë€½5€Ûº½5€ô$Y ŽÃ1-1-Y˜–€Us7777ºBUFRöbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<΂UUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷½ï{Þ÷€„!B„!B„!D!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œc!B„!@Š!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ \†G ŽèHIðdpýàReÀ¤ËbŸ¼Ä´?x~ð X€@½5zk“.c ¸Ø“à#`-ÆÀ±Y=b>?x q°Ö 3á@jI>ÃP @ 'À9ûÀÃPŸ ôÖ¡ ~ð¦°#`3á@OX€†G ŽIð¦°&% LK@¤Ë€çï²é¬ »  /M`^šÀÏ…·tõˆ|( L¸jð !‘À$Ÿj’|ÐÐ,@ X€@±bÐdpЦ°,@ F0À[€ž±ÃP† ?x~ðÈàO€†GÏÞ€!‘À3á@g€ô$èHÐÝÐ øP#`I>¡¾A$ø·Íõˆ äÖ 0ÔX€@= I> Žˆ~ðw@6î€a¨Ûº7777ÕBUFRæbÿ« fÎ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀ0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUPUUUU@UUUUPUUUUð `Œa€g€g€Éj€ÛºYÃô$Ûº€,€= ±²| 5+Ä~±²|s÷1-tP˜ïh1- ŽÛºô$=b¥$¥$ÉÀ…hh=bÃçïô$çïÕŸ€ÕŸ€½5€½5€Éj€Éj€Éj€çïô$Éj€Éj€ÕŸ€Éj€±€½5€ÛºŒa€[€¤Ë€[€$Ÿ 5 5±²~7 ú—‚7 ‚7 €$Ÿ¤Ë€Œa€g€[€g€€,€½5I—ÃÕŸ€ÕŸ€€,€= = 5±²}€…€…€…ú—€j¤Ë€Éj€¤Ë€UsI>Usg€ŒaYI—¥$½ŽhI—Ã Ž€,€ 57 ‚7 €= [€±YÛº€,€s÷€[€Uss÷€çï±€ÕŸ€¤Ë€˜–€7777î€BUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀ(0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUPUUUUUUUUUUUUUUUUUUUUUð `Éj€˜–€Œa€UsUsg€s÷€¤Ë€Ûº˜–Y1-tP=b=b¤Ë€¤Ë€ô$ Ž1-1- Žçï ŽÛºs÷€I> 5j 57 €…ú—‚7 €0ÔŒaÃ[æÃ=bÕŸ€ô$äˀ¤Ë€½5€½5€Œa€Œa€[€$Ÿú—‚±²}ú—€…‚±²|$ŸŒa€ô$ Ž1- Ž1-$ø$øI—UÌŒºhtP[æhI—ŒºUÌ1- ŽYY€,€Œa Ž Ž Žçï±€ÛºÉj€€,€s÷€˜–€¤Ë€˜–€g€$Ÿ[€g€¤Ë€˜–€¤Ë€€,€0ÔI>s÷€0Ô$Ÿ$Ÿ$Ÿ0ÔUsUsŒa€˜–€Œa€Œa€ŒaYçïYÉj€½5€ÕŸ€˜–€I>Us$Ÿ0Ô7777î€BUFRÆbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀ@0$’I$’I$’II$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èKçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@)2à` 5C#€Ûºh[æ ŽYYô$YC|«?ÏÞ¥$Œº¥$¥$‚·ÍÐ7ÜlÜèHtPŒº[æ«?+k‚Ð7%Q\?ƒPcƒ+Ä€ÃPÛºô$Ý+[æ+ÝÃ7GÃô$ô$çïÛºÛºçïYtP«?·tÏÞÜ·t¥$«?«?€…Ý7GYà ŽYÏ…Ûºçïçï·ÃPÛºÛºÛºªæÛºÛºçïۺυۺô$ô$Yô$ô$ô$ۺυçïž±Œa€ž±··Ï…çïÏ…Ï…ªæž±˜–€ÃPYYYô$çïۺυªæž±˜–€˜–€s÷€C#€6î€s÷€˜–€ž±˜–€€,€˜–€ž±ÃPÏ…7777ÉjBUFR¶bÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÀT0 $’I$’I$’RI$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2-pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]èHnèÝÐ-P5gàdµ@˜–b1†IðW0¡ jjÃPÜl ‰h™p,@ dµ@Ûº·tС B@„€C#€s÷€ô$zkĈ ™p&% jÏÀçïõˆ L¸™p#`C#€’|=bzÄ&\ ®`Ð+|Ð= †GYÏÞnè¡ »  ýà^šÀÉjèHõˆ ëŒ0&% C#€€,$øzÄ n ,X0°Vù ¤Ë=b1†28ÆŒ0 9ûÀ€,Ã1†õˆ ŠÌ¸0°] ¤Ë1-è¡”’ eÔRH.Šc. ªæh‚·Í“à L¸¾h#`= €, ŽèHnè?x » „€F0ÀX€@çïÏÞnè?x Yø 5gàmÝÛº7777±BUFR&bÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎÂUUUUUUU\ëZÖµ­kZÖµ­kZÖµ­o{Þ÷½ï{Þ÷½ï{Þ÷½óœç9Îsœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{Þ€„!B‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%LkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUEUUUUUUUUUUUUUUUUUUUUUUUUýà`g€I>I>OX€= Œa€¤Ë€˜– Ž=b[æh1-1-I—$ø=btP[æ1-çïÛºçïÉj€±€½5€¤Ë€€,€$Ÿ|jI>€,€¤Ë€Ï…Ï…YÉjÃI—I—=bI—1-$ø$ø1-O±YçïçïÏ…½5€Œa€¤Ë€Éj€ô$ô$Éj€Œa€Œa€±€±Y=b$øÉj€Éj€Ï…½5€¤Ë€±€€,€s÷€= I>[€¤ËYO±hI—Ã$ø$ø ŽÃà Ž$ø Ž1-Yô$ÛºÛº½5€±€˜–€Œa€˜–€±€Ï… Ž=btP€…h$øô$Éj€ô$Y ŽYYçïÉj€±€Œa€[€I>I>OX€€,€Éj€çï7777º‚BUFRæbÿ« fÎ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUTUUUUUUUUUUUUUUUUUUUUUUUUUUð `ô$ Žô$½5€ÕŸ€ÕŸ€½5€Ûº Ž$ø=bô$½5€¤Ë€ÕŸ€Éj€Œa€Usjú—‚7 €$ŸYÕøÕøtP€çï½5€Éj1-1-I—1-=b$ø Žô$ÕŸ ŽÉj€s÷€[€j$Ÿ¤ËI—€…€…1-Ãçï$ø$ø[æUÌ1-ÃYçïÛºçï¤Ë€g€€,€±€[€[€= Œa€ÕŸYÛºŒa€±ÃI—I—tPŒºtPI—$øô$ô$YÕŸ€ÕŸ€ô$çïô$½5€€,€±€çï$ø ŽÕŸ=b ŽÛºYYUÌtPŒº½Žâ-¥$tP=bÃà Žô$ô$ô$ ŽI—tP$øh=b€…[æh[æ€7777øBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ð‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUPUUUUUUUUUUTUUUTýàaI—1-$ø ŽYYô$çïçïçï¤Ë€OX€I>$Ÿg€€,€¤Ë€Éj€ÛºÏ…ô$ô$ Ž$ø1-à Žô$ۺυۺçï¤Ë€½5€±€±€€,€˜–€½5€Ï…ÃÃô$Ûº¤Ë€±Ã Žô$ô$Yô$ô$ô$½5€½5€I>I>~¥}~¥}| 5g€€,€¤Ë€˜–€˜–€Œa€€,€Œa€¤Ë€½5€çï=bÃÏ…ô$1- ޽5Y ŽÃÃô$ÛºÃ$ø€…I—Y=btPO±ÃYÃçïÉj€±€s÷€[€ 50Ô$Ÿ 5~+k‚¥}| 5$Ÿ€,ñ€½5€çï Ž Ž Ž1- Žô$$ø ŽÉj€+k€7777øBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î40I$’I$’I$”’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©l|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUTUUUUUUUUUUTUUUUUUUð a€…€…s€Œa€Œa€Œasƒ+Ä|$ŸÉj€ÕŸ€€,€s÷€½5€çïô$±€±€€,€I>0ÔUsj7 ‚7 ‚7 €…€…‚7 €[€Œa€Œa€½5€¤Ë€˜–€s÷€Usg€€,€±€˜–€˜–€I>g€g€0Ô 5±²|$Ÿ±$øI—tP€…hŒº$øI—YhI—[æ[æI—$øÕŸ€±€s÷€g€I> 5[€Éj=bI—UÌ[æI—ÃçïçïI—I—UÌ=bçïô$Éj€s÷€g€ 5+Ä~±²~±²~7 €$Ÿ¤ËYÃô$ô$ÛºÉj€ô$Ûºô$ô$ÕŸ€çïs÷€I>I>I>j0Ô 5 50Ô½51-[æÃ7777øBUFRæbÿ« fÎ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎH0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð a$ø[æI—Ã$ø=b Ž1-Yçï ŽÕŸ€g€I>0Ô+Ä|±²~±²~±²+Ä|j$Ÿ$ŸI>I>I>Œa€˜–€¤Ë€½5€½5€½5€çï Ž Ž1- ŽÛºŒa€= jjI>I>g€I>s÷€€,€€,€ÕŸ€¤Ë€±€Éj Ž ŽY$ø1-Ãçï ŽÉj€ô$ Ž ŽÃÃô$çïUÌ[æ¥$ŒºUÌUÌ[æI—tP[æ=bçïçïYô$ÛºÉj€±€˜–€¤Ë€¤Ë€±€½5€ÛºÛºYà Žô$Ãô$Yçïçïô$ ŽÕŸ€½5€±€Œa€s÷€I>[€s÷€€,€Œa Ž$ø=b[æI—Œº˜ïtP¥$˜ï€…€7777øBUFRæbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Î\0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUPTUUUUUTUUUUUð atP[æUÌI—=b1-$ø=bÃô$½5€Éj€±€ô$UÌI— ŽÛº=b$øçïô$½5€¤Ë€[€s÷€s÷€= 5 5±²}€…€…ss‚7 ƒ+Ä~±²|= ±€Us0Ô 5+Ä~7 €jÉj€ú—€…€O€…s€O€Œa€Œa€Œa‚±²|Us[€= jj+Ä| 5+Ä}€…€…€…s€…s€O€Œa€Œa€Œas€…€ 5Œa€I>j0Ô[€[€±€½5€½5$øÕŸ€Éj€ÛºÉj€ÕŸ€Œa€I>7 ‚±²~7 ‚7 €j 5[€€,€g€= $Ÿ 5j= s÷€ÕŸY Ž$øÃ$ø1-YÛº0Ô7777øBUFRfbÿ« fÎ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÎUUUUUUUUUUUUUTD»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»^sœç9Îsœç9Îsœç;Þ÷½ï{Þ÷½ï{Þ÷½ï}ï{Þ÷½ï{Þ÷½ï{Þ÷€B„!B„!B„!„!B„ Š!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUPUUUUUUUUTUUUUU@ð `$Ÿ$Ÿj[€Éj€Éj€Éj€˜–€Œa€˜–€€,€g€€,€Œa€I>[€[€g€s÷€Œa€= j 5$Ÿ±²}ú—ú—ú—‚7 € 5= [€Œa€±€±€Éj€çï1- ŽÃçïŒa€¤Ë€˜–€¤Ë€±€ÕŸ€ÛºI>j+Ä~±²+Ä|jg€Usg€0ÔI>[€€,€±€€,€Œa€s÷€±€€,€g€I>= ½5€[€= 5$Ÿ= 0Ô0Ô= 0Ô0Ô= = Usg€I>= 0Ô0Ô$Ÿ+Ä+Ä}ú—‚7 €…€…ú—ƒ+Ä|0Ô€,€Éj€Œa€€,€˜–€s÷€g€Œa€±=b1-YYÕŸ€˜–€€,€s÷€€,€I>0ÔI>±²~±²~7 ƒ+Ä|$Ÿ¤Ë€I>7777BUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@ 0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUQUUUUUEUUUUUUUUUUUUUUUUUUUUUð `Œa€s÷€s÷€[€ÕŸ±Y¥$[æ Ž±€= j$Ÿ+Ä|+Ä+Ä|= ±€ô$ÃÃÉj€Éj€g€s÷€˜–€˜–Yô$YÕŸ€½51-1-Œa€0Ô$Ÿ±²|$Ÿ¤Ë Ž Ž Ž Žçï Ž$øYô$ô$YÛºô$ÕŸ€¤Ë€Us$Ÿ= 0Ô0Ô= Us˜–€Éj€½5 Ž$øÃh€…˜ïŒºŒº˜ïtP[æhÃ[æÕøI—Éj€€,€Usg€Œa€ÕŸÃ[æh[æ$øhŒºh=bô$=b$ø$øÃÉj€˜–€Us= $Ÿ 50ÔUs¤ËU̘ï¥$tP€…tP¥$ÉýŽÉØïI—77770ÔBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@ 0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDýàa$øô$¤Ë€Ûº=b=b1-Éj€¤Ë€€,€Œa€Ï…1-[æI—ÃY Žçï$øY[æhO±O±I—I—1-$øçï Žô$Éj€˜–€s÷€OX€OX€s÷€s÷€±€€,€Œa€Ûºçï$øI—[怅tPŒº¥$Œºhäˀs÷€€,€Œa€±$ø€…˜ï˜ï€…¥$tPtPtPh½ŽÕø‚ çÜ1†Ü ç½ŽÕøO±I—YYÏ…ÛºYô$çïçï ŽI—I—€…hO±tP=bÏ…Ï…˜–€Œa€OX€I>I>0ÔOX€0Ô0Ô[€çÉÃ½ŽŒºtPI—h ŽO±=bI—çï€,€[€OX€0Ô|+k€77770ÔBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@80$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠ2ÇBT×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUQUUUUUUUUUUUUUUUUUUUUUUUQUUð b7 ƒ+Ä|$Ÿ[€çïYY$ø¤Ë€½5€ô$çïçïçï[€[€s÷€= j$Ÿ0Ôj+Ä|j= Us¤Ë€ÕŸ€ÛºÛº˜–€±€€,€¤Ë€˜–€±€Éj€Éj€Éj€½5€˜–€[€g€I>= $ŸI>˜–[æ˜ïYçï±€˜–€€,€½5Y1-=btP[æ€çïtP Žô$€,€0Ô0Ô$ŸjI>I>½5€ô$ô$Y½5€½5€Œa€¤Ë€½5€Ûºçï1- Ž$ø Žô$çïÛº[€[€Us˜–€€,Y=bUÌ=bô$çïÛºô$ÕŸ€Éj€Éj€ÛºÕŸ€½5€çïÉj€çï½5€I>jj+Ä|jjUs½5€ÛºÛºçïÉj€Éj€77770ÔBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@L0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUUUUUUUUUUUUUUUUUUUUUUUUUUUUýà`½5€½5€½5€çïYO±€…tP$ø Žô$s÷€j 5|$ŸÉjÃ[ætPà Žô$Ã$øI—½Ž€…¥$€…O±$øtPI—O±Ãô$YYÃÃ[挺€…¥$€…Œº ŽY[怅I—[æhhO±I—1-ÃYçïÛºÛºYO±=bhtP€ô$ ŽYÃ=bO±[æhI—1-I—=b1-Y±€s÷€˜–€½5€½5€Ï…çï=bçïÏ…ô$ ŽÃçïÛºçïçïÉj€±€Œa€g€˜–€s÷€g€€,€I>OX€I>j[€½5€ÛºÛºô$½5€Éj€˜–€çïô$Ï…Ï…¤Ë€s÷€[€77770ÔBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@`0$’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ý¶Û`‹[\ÈS RØ×>•+k€" c¡*[çÂ2+k€" c¡,kŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUUUUUUUUUUUUUUUUUUUUUUUUUUUUýà`= I> 5+kƒ}tPîb‚+kƒ| 5OX€Ï…Ãçïg€g€g€±€[€s÷€˜–€Œa€±Y˜–€½5€OX€= $Ÿj= €,€Ûº Ž[æ€ô$Éj€½5 ŽŒº$øO±YÛº½5€Éj€½5€€,€I>j 50Ô 5OX€Éj=b€…Œº€…O±Œº=bŒº€…1-ô$Ï…s÷€I>= 0Ô[€OX€0Ôjs÷€g€ô$=bçï±€½5€˜–€±€±€Éj=bh[æ1-$ø1-Ï…Ã Ž1-Ã=bYY[æèH€Þ‚ ç¥$ ŽÏ…Y=b=btPO± ŽÃ Žô$ Ž1-=bI—$ø ŽÛºÉj€Éj€Éj€77770ÔBUFR&bÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏBUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï{ß{Þ÷½ï{Þ÷½ï{Þ÷½à„!B„!B„!BB„!B„!B„!ŒcÆ1ŒcÆ0Š„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUPUUýà`Ï…çïÏ…±€˜–€±€˜–€¤Ë€½5€Ï…Ï…Éj€±€ÛºÉj€±€˜–€±€s÷€I>I>I>OX€s÷€Œa€˜–€¤Ë€€,€˜–€¤Ë€Œa€¤Ë€½5€Éj€Ûºçïô$ ŽÏ…Ûº±€€,€s÷€g€Œa€¤Ë€Ï…Y=bÃ$ø Ž ŽçïÃ1-O±˜ï˜ïh[æ1-$øô$ÃYs÷€jI>Ï…Y[æ˜ïO±[æh€…h=bÃtP¥$tP€…€…I—I—O±$øÏ…±€OX€= s÷€ô$1-O±tP=bI—ÛºYô$=b[ætPhO±€ô$Œa€€,€= 5¥}}tP‚¥}~¥}| 5€,€˜–€Œa€s÷€[€OX€$Ÿ$Ÿ= 7777bBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’Km¶Ûm¶Ûm·m¶Û`‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©l­®ˆd)Ž„±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUýà`[€Œa€s÷€$Ÿ$Ÿj$Ÿ¥}~¥}~+k‚+k‚¥}| 5js÷€½5€½5€±€±€s÷€s÷€€,€˜–€¤Ë€½5€Ï…s÷€OX€g€OX€$Ÿ 5j 5= g€½5€˜–€Œa€˜–€¤Ë€Œa€˜–€˜–€±€½5€˜–€s÷€[€[€I>OX€0Ô= $Ÿ$Ÿjj0Ô= OX€0Ô= 5 5 50Ô= OX€±€Ï…Ï…±€ô$Y½5€€,€I>jjj[€ŒaO±±Y±YtPtPI—ÉÃ½Ž€…€ÛºŒa€OX€0Ô[€s÷ Ž[æ˜ïO±Yô$1-1-=b¥$Ü¥$˜ï˜ïtPhI—±€g€I>= [€±1-tPI—7777a€BUFRÆbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€(0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@3á@`˜–€˜–€€,€Œa€€,€½5ÃI—1-ÃYî €ÕŸYYYáÔ€ô$ô$î €ô$n61-I—ÃYÃ$ø1-1-zk€…zkbzk€…UÌ=bÃ=b Žô$î Y1-€…ÉÂbZ¥$bzkI—±Yn6zk±Y±Y˜ï˜ï¥$n6UÌ=bYáÔ€Éj€ÕŸ€áÔ€±€½5€¤Ë€˜–€Œa€s÷€Us€,€Œa€±€î $ø=bI—ÃYáÔ€î €½5€Éj€Éj€s÷€ 5$Ÿ= Uss÷€€,€±€½5€½5€±€˜–€áÔ€áÔ€î €ÕŸ€Œa€˜–€UsUs= $Ÿ= 0ÔI>˜– ŽYn6b Ž Ž¤Ë€±€a¨±€€,€½5€7777gÂBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€<0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUEUUUUUUUUUQUUUUUAUUUUUUUUUUUð `çïô$ Ž$øô$½5€˜–€= j+Ä| 5jUsÕŸ ŽÉj€˜–€˜–€€,€s÷€¤Ë€˜–€Éj€Éj€±€˜–€s÷€= jjjj7 € 5j¤Ë=btPÃÛº±I—1- ޽5ÃhUÌhI—çïŒa€$Ÿ+Ä|±²~±²~±²| 5= Œa€Ûº¤Ë€Œa€Œa€¤Ë€±€ÛºÛº¤Ë€ÛºçïÛºÛº¤Ë€€,€I> 5j±²+Ä|jI>Éj=bô$¤Ë€g€g€՟€ô$Y$ø[æUÌI—h€…€Éj ŽI—=b=b±€¤Ë€s÷€s÷€ÕŸÃÛº±€s÷€Us[€= [€= Usg€s÷€s÷€Éj€±€€,€ 5 57777a€BUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€T0’I$’I$’I%$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@UUUUUUUQUUUUUUUUUUUUUUUUTUð ` 5+Ä}€…ú—ƒ+Ä}ú—ƒ+Ä~±²| 5 50Ôj$Ÿ0Ô 5$Ÿj 57 ‚±²}€…ú—sú—sú—€I>˜–€ÕŸ€s÷€s÷€= I>= Us˜–€¤Ë€˜–€s÷€€,€I> 5±²|7 ‚±²+Ä|jg€çï=b$øçï¤Ë€ÕŸ€½5€çï=bh Žô$ô$±€Usj= 5$Ÿ$Ÿg€½5€ÕŸ€½5€¤Ë€¤Ë€€,€Us€,€s÷€€,€±UÌŒº€…[怅‚1†%Q1†¥$[æh1-Éj€½5$ø1-ô$ÛºÕŸ€ÕŸ€ÛºçïY Ž$øtPI—çï¤Ë€¤Ë€[€Us$Ÿ±²+Ä| 5Usô$hÃçïY7777a€BUFR&bÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï‚UUUUUUUUUUUUUUUUU\ç9Îsœç9Öµ­kZÖµ­kZÖµ­kZÞ÷½ï{Þ÷½ï{Þ÷½ï{!B„!ŒcÆ1ŒcÆ1ŒcÆ2„!B„!B„!@ŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èKŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUTUUUUTUUUUUUUUUUUUUýàa€…hhhÜÕøÜÉØï=btP=bÉj€¤Ë€Œa€g€I>OX€€,=bçï½5€g€I>OX€0Ôj= [€€,€ç€[€Ï…OX€jj 5j¥}}îb€ 5$Ÿg€I>$Ÿj$Ÿjjj$Ÿ[€s÷€g€[€0Ôj~+k‚¥}|jI>€,€€,€±€ÛºÏ…½5 ŽÉj[æÃ1-çï1-1-ô$Ûº¤Ë€¤Ë€¤ËY1-YÉj€½5€±€¤Ë€Éj€Éj€ô$1-1-ô$½5€Œa€I>$Ÿ¥}|+k‚¥}~+kƒ|= ˜–€ÛºÏ…˜–€½5€½5€½5€±€¤Ë€Éj€Ï…ÛºY±€I>$Ÿj7777bBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©ll#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUAUUUUUUUUUUQUUUUTUUUUUUUð `= = 0Ô$Ÿ= I>[€Œa€ÕŸ€çïô$ÃI—1-I—=b=bUÌ[æ$øI—I— ޽5€¤Ë€˜–€I>±²+Ä|jjj$Ÿ= g€g€s÷€Œa€˜–€¤Ë€Œa€€,€Œa€Œa€g€g€I>I>$Ÿ$Ÿ0Ôs÷ÃUÌUÌ$ø1-Ãñ€[€€,€¤Ë€ÕŸ€ÕŸ€¤Ë€½5€±€[€0Ô 5j+Ä| 5j0ÔÉj€ô$ÃY$øYÛºÕŸ[æ[æI—YÛºÕŸY±€j+Ä~±²~±²+Ä|jUsô$çïô$ÕŸ€g€s÷€= [€€,€€,€ÉjtPâ-ÕøŒº$ø¤Ë€Usg€[€€,€¤Ë€ÉjYYô$ÕŸ€7777|BUFRÆbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ,0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥µÏ„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@&% `[€OX€s÷€Œa€ªæYô$ ŽÛº·ô$Ã+7G7GC|+7G7GO±tP¥$±Y¥$¥$h€Ûº7GO±tPtPtP±Y€…tPŒº±Y7G+Y ŽY++C|ÃçïÏ…¤Ë€¤Ë€[€˜–€¤Ë€s÷€· ޱYtPéhtP7G+€ô$çïÃPŒa€[€€,€¤Ë€¤Ë€*¹€s÷€ 5$Ÿj 5$ŸŒa ŽèHÜéé˜ï7GÃÛºªæ¤Ë€ÃPçï[ætP€…êæ·s÷€€,€·ô$7G‚ ç²Ü ç²·tŒºhÃô$ÃPY+h˜ï+€Ï…ÛºÛºçï+€…·tÏÞ7777[BUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ@0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUPð b çÕøâ-ÕøÉÀ…UÌ=bÕŸ€ÛºÃI—ÉÃèH²UÌÃtP1- ŽtP€…€…Õøâ-‚%QIð%Qâ-±Y€…=bÃYÃY Ž=bÛº¤Ë€¤Ë€±€Œa€¤Ë€±€Ûº Ž1-Ãô$$øÛº½5€¤Ë€€,€[€I>I>= €,$øUÌYçïô$à Žô$ÛºÃÃUÌ€…htP[æ=bÃÕŸ€±€s÷€g€I>˜–$ø ŽçïÉj€€,€¤Ë€Œa€˜–€¤Ë€ÕŸYçï±€¤Ë€s÷€€,€[€0Ô 5 5±²~7 ‚±²+Ä| 5 5$Ÿ$Ÿ[€$Ÿj= [€jŒa€g€I>$Ÿ= +Ä}ú—€7777|BUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀX0’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5ÐŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUUUUUUUUUUUUUUUUUUUUUUUýàaîb‚¥}|s÷€çï½5€¤Ë€Ûº¤Ë€¤Ë€¤Ë€¤Ë€¤Ë€˜–€Éj€Œa€s÷€±€g€€,€Œa€I>~¥}}tP‚¥}| 5[€Œa€s÷€s÷€[€˜–€s÷€€,€Ï…Éj€˜–€¤Ë$øÃ1-Ûº0Ô0ÔjI>I>gÂ1-[æ ŽÏ…½5€±€Ï…Œa€Œa€½51-ÜtP1-çï½5€Éj€¤Ë€s÷€[€OX€= Œa€Ûº ޽ހ½5€Ï…ô$ ŽI—€…htP˜ï[挺€…[æ€Ûº½5€g€I>0Ô0ÔOX€g€±YYY˜–€˜–€[€[€˜–€s÷€¤Ë€Éj€Ï…¥$€…€Éj±Y[æ Ž±€ÛºŒa€Œa€±Y=b$øÛº€,€¤Ë€7777|BUFR&bÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÂUUUUU]kZÖµ­kZÞ÷½ï{Þ÷½ï{Þ÷½ï{ç9Îsœç9Îsœç9Îsœï{Þ÷½ï{Þ÷½ï{Þ÷½÷½ï{Þ÷½ï{Þ÷½ï{ފƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUTUUUUUUUUUUýà`¤Ë€¤Ë€s÷€Œa€Éj€Ï…ÛºtPh[æ1-I—¥$hI—I—ۺυÉjYŒa€½5€OX€s÷€OX€I>g€OX€s÷€˜–€¤Ë€¤Ë€Œa€€,€0Ô$Ÿ¥}~¥}~+k‚+k‚¥}|jOX€±€˜–€¤Ë€˜–€˜–€Éj€¤Ë€½5€½5€ô$=bO±tPtP±Y€…tP€çïÉj€Œa€Œa€OX€çïtP€…[æ€ÛºçïÉj€ÉjÃÛº ŽÃô$ô$Ûº¤Ë€±€Œa€s÷€= $Ÿ 5|€,€ô$[æ=bÛº±€±€½5€Œa€½5€Éj€½5€½5€¤Ë=bÏ…s÷€$Ÿjj[€I>OX€[€¤Ë€çïYÛºÉj€Œa€s÷€€,€OX€OX€[€s÷€¤Ë€¤Ë€½5€7777bBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUPUUUUUUUUUUUUUUUTð `Éj€¤Ë€¤Ë€Œa€s÷€çïô$ÕŸ€€,Y1-UÌUÌUÌÉj€Œa€¤Ë€½5€¤Ë€s÷€˜–€ÛºçïÕŸ ŽI—UÌ1-ÃÕŸ€¤Ë€= = ±€ô$ ŽÉj€j0Ô0ÔI>0Ô+Ä+Ä|0Ô±€ÛºŒº˜ïŒº˜ï$ø½5€½5€I>jjI>s÷€ÕŸ€€,€Éj€¤Ë€˜–€[€€,€Œa€˜–€¤Ë€ô$½5€Éj€±€s÷€g€I>+Ä~±²}€…€…€…‚7 ƒ+Ä|= I>$Ÿg€Us$ŸI>s÷€±€ÛºÛºçï±€Œa€Usj±²+Ä}€…€Oú—‚7 €j[€= 5 5 5 50Ô= UsUsUsI>j0Ô±²+Ä| 57 ‚7 €7777€BUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠB˜èJØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUPUUUUPUPUUð b±²|j¤Ë€Éj€±€ÕŸ€Œa€¤Ë€ÕŸ€±€Éj€ÕŸ€Éj€¤Ë€Œa€UsI>[€I>j[€$Ÿ= s÷€çï1-Œº€ÛºÉj€çï Ž1-$øô$½5€½5€½5€½5€ÕŸ€ô$ÕŸ€Éj€±€˜–€±€Œa€g€˜–€Œa€¤Ë€ô$Ûº¤Ë€s÷€Œa€g€Usg€s÷€s÷€Œa€ÕŸ[æUÌtP€ô$çï[€Us 57 ‚7 ƒ+Ä|$ŸŒa€Us0Ô 50Ô0Ô0Ô0ÔjUs 5$Ÿ$Ÿ$ŸI>0Ô$Ÿ$Ÿ€…€…ú—‚7 ‚7 ú—‚7 ƒ+Ä|±²~±²~7 ƒ+Ä+Ä|j[€[€0Ô$Ÿú—€…‚±²}ú—€…‚7 €$Ÿ˜–€Ûºçï¤Ë€s÷€Usg€7777€BUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï00$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `s÷€½5€Éj€çï€,€€,€= = $Ÿjú—ú—ƒ+Ä~±²| 5g Žçï±€€,€= €,€±€g€$ŸI>±€ÛºŒa€ô$ÃUÌtPUÌ1-=bI—UÌI—hŒº‚%Qô}h$øçïÛº±€¤Ë€½5€Éj€ÕŸ€˜–€ÕŸ€…UÌ¥$€…Y$ø ŽYÕŸÃ=bŒºŒºñ€±€€,€€,€¤Ë€ÕŸ€ô$ Ž$øŒa€¤Ë1-hY½5€s÷€= [€€,€½5UÌI—I—tPh¥$ ŽÛºÛºÛºUÌ1- ޽5€˜–€˜–€€,€I>I>$Ÿ$Ÿ0Ô½5€ô$ÛºŒa€0ÔjI>½5€±€€,€½5€Ûº1-1-ô$çï7777€BUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏD0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUQUUUU@QUUUUPUUUUUUUUUUUð `ô$¤Ë€¤Ë€Œa$ø$ø$øÃçïÉj$ø1-˜–€½5€¤Ë€I>= [€0Ôs÷€UsUs½5 ޱ€g€Œa€Éj€= +Ä|$ŸŒa€çï=b¤Ë€= I>Us0Ô0Ô= = UsI>0ÔUsI>+Ä~±²~7 €$Ÿ 5+Ä|$Ÿ= Us¤Ë€½5€Œa€Œa€€,€˜–€¤Ë€˜–€¤Ë€˜–€Œa€˜–€ô$¤Ë€g€ú—ƒ+Ä}ú—‚7 €0Ô€,€¤Ë€¤Ë€UsŒa€I>[€s÷€[€€,€˜–€Œa€˜–€¤Ë€Œa€±€˜–€[€j+Ä~7 ‚±²|0Ôs÷€ô$ Ž¤Ë€¤Ë€±€g€UsI>Éj€˜–€[€± ŽhÃô$Œa€0Ôg€0Ô0Ô$Ÿ±€7777€BUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï\0 $’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[èFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUU@@UUUUU@UEUUUUUUð `±YÕŸ€˜–€s÷€¤Ë€Éj€±€¤ËUÌI—tPI—hh[æ$øY¤Ë€½5€Œa€˜–€˜–€±€½5€ÛºÕŸ€¤Ë€Ûºô$ Žçïô$ÕŸ€çï=bÕø Ž$øÃçïñ€[€I>j$Ÿ0Ô+Ä+Ä~±²|+Ä~±²+Ä|j 5 5j$Ÿ$Ÿ 5±²}€…‚7 ‚7 ‚±²+Ä|s÷ Ž ޽5€±€g€jj= 0ÔŒa€Œa€[€ 5 5+Ä+Ä}ú—€…€…‚7 €…€…ú—€ 5I>¤Ë€¤Ë€g€Us+Ä|$Ÿjjj0Ô[€€,€g€$Ÿj 5I>Éj Ž1-Ûºg€I>I>$Ÿ$Ÿj7777€BUFR&bÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏUUUUUUUUUUUUUUUUU]ï{Þ÷½óœç9Îsœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{Þ€!B„!B„!BˆB„!B„!B„ ŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUAUUUUUUUUUUUUDUPUUUUUUUð `j$Ÿ$Ÿ 5 5 5 5ú—ú—€…‚7 €…s€…‚±²|= s÷€g€[€$Ÿ+Ä+Ä|±²|jUsg€s÷€[€Usg€UsUsÕŸ€Ûº1-tPÉÃh1-Ã1-Œa€€,€¤Ë€ô$€,€Us[€[€Us[€$Ÿ+Ä| 5$Ÿ 50Ô0Ô[€½5€Ûºô$ Ž ŽÉj€½5€Éj€Éj€çï±€€,€±€g€0Ô0Ô0Ô7 €7 ú—ú—‚7 ƒ+Ä| 5$Ÿ$Ÿ 5j 5+Ä+Ä~±²|j 5I>g€[€Œa€$Ÿ$Ÿj= jI>s÷€ÉjYÃ Ž Ž€,€0Ô$Ÿj$Ÿjj= I>Œa€[€[€±€7777bBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@ 0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ý¶Û`‹pC!Lt%Kc_Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTUUUUUUUUUUUUUUUUUUUUUUPð `½5€g€[€j 5j0Ôs÷€€,€g€0Ôjjjjj0Ô 5 5j 57 ‚7 ‚±²~7 ‚7 ƒ+Ä|I>¤Ë€Œa€g€Us$Ÿjj= Usg€s÷€I>s÷€çï½5€s÷€g€Us= I>[€Œa€¤Ë€±€ÕŸ Ž ŽYçïçï¤Ë€ÛºÃUÌI—h[挺ŒºÃÉj€¤Ë€Usg€€,€Ûºç€€,€UsI>I>$Ÿ= €, Žô$[ætPtP€ÛºI—1-I>js÷€0Ôj0Ô0Ô˜–€¤Ë€±€s÷€s÷€€,€€,€˜–€½5à Žô$=bçï±€Us€,€€,€ 5 57 s€…€…€$Ÿ€,€7777÷€BUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@$0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUTUUUUUUUUUUUUUUUUUUUUUUUUUð `Us= [€= I> 5j+Ä+Ä| 5 5$Ÿ$Ÿ0Ô0ÔI> 5±²+Ä|[€ÕŸÃÛº½5€±€g€çï±€Œa€±€Éj€˜–€±€çïÕŸ€Œa€0Ôj+Ä|±²+Ä|j[€ô$ÕŸ€ÕŸ€ô$ÛºÕŸ€½5€±€Œa€¤Ë€çïçï¤Ë€Éj1-Ãçï½5€= 0Ô$Ÿ 5j0Ô€,YŒa€±€Œa€Œa€I>[€= ¤Ë€ÕŸ€ç€Œa€Éj$øÉjÃI>0Ô 5 5$Ÿ= ˜–€ÕŸ€Éj€Éj€ÕŸ€Œa€˜–€˜–€½5€˜–€Ûºs÷€[€ÕŸ€ÕŸ€ÕŸ€ÛºI—˜–€= 0Ô€,€ô$ ŽÃÕŸYÛº¤Ë€Us= ÉjI—7777÷€BUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@80I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ð‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTADEUPTUUUTUUUUUUUUUð aI—ô$Œa€Uss÷€g€g€Us0Ôj±²~±²|$Ÿ0ÔI> 5±²+Ä|= 5±²| 5±²|j+Ä|I>[€[€= I>[æ€$Ÿ+Ä+Ä~±²|0Ô0Ôj7 ‚±²+Ä}ú—€…€…ú—‚7 ƒ+Ä~7 ú—ƒ+Ä| 5ú—‚7 ‚7 €…‚7 ú—€jI>I>= = I>0Ô0Ô$Ÿ$Ÿ$Ÿ0Ô$Ÿjjj 5 57 ú—‚7 ú—€…‚7 €0ÔUsg€€,€0Ô0ÔI>0ÔUsI>I>= [€I>= 0Ô0Ôj 57 €7 ƒ+Ä|j˜–€çïÛº½5€±€¤Ë€s÷€g€Us¤Ë€Œa€˜–Ãs÷€g€Œa€g€±€Us7777÷€BUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@P0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Ûm¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©n|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUT@@UUUUUUUUð `$ŸI>0Ô 5I>ÛºI—h½ŽÉÃŒº1- ŽYUÌÕŸ€çïÕŸ€½5€Ûº[æ€ô$±€g€[€g€Œa€ÕŸ€Ûº½5Y$ø¤Ë€€,€g€s÷€Us€,€Œa€s÷€Us[€€,€ÕŸ€Éj€I>I>= j[€0Ô 5$ŸUss÷€I> 5$Ÿ= $Ÿj$Ÿ 5 5I>= 57 €+Ä+Ä}ú—ú—ú—€$Ÿ 5= +Ä+Ä+Ä+Ä+Ä|jj 5$Ÿ= 0Ô= s÷€ 5±²~±²~±²~±²+Ä|$Ÿ€,ÃÕŸ€€,€= g€˜–€˜–€s÷€I>= $Ÿs÷€g€[€[€$Ÿ[€j= s÷€€,€€,€s÷€s÷€= 7777÷€BUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@d0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUPEUUUUUUUUUUUU@ð `I>I>I>0Ô0Ô[€s÷€[€[€Œa€ô$ Ž˜ï€ÕŸ€[€I>j0Ô0Ô[€€,€çïô$±€½5€s÷€Œa€½5€˜–€Usg€[€UsÛºÛºYçï€,€€,€¤Ë€½5€±€±€¤Ë€ô$[ƒ+Ä+Ä|+Ä| 5+Ä| 5 5$Ÿ$Ÿ0Ôs÷€±€±€$ŸjjUs[€$Ÿ$ŸŒa€s÷€Œa€Us€,€s÷€= = 0ÔUs0Ô= 0Ô[€˜–€çïô$ÕŸ€Éj€±€Œa€˜–€¤Ë€s÷€€,€˜–€˜–€Éj€€,€±€$Ÿ 5±²|= ¤Ë ŽYŒa€I>j 5±²~±²+Ä}s€…ssss€…ú—‚7 ƒ+Ä~±²+Ä~7 € 5+Ä|7777÷€BUFR&bÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏBUUUUUUUUUUUUUUUUUUUUUUUU^÷½ï}ï{Þ÷½ï{Þ÷½ï{Þ÷€B„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œ„!@‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èKçÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUPUUUUQUUUUUUUUUUUUð b±²|±²| 5+Ä}€…s€…sú—€…€…‚7 ‚7 ‚±²~±²}ú—€ 5$Ÿj±²|$Ÿ+Ä|= j$Ÿ 5 5j 5j0ÔI>s÷€¤Ë€½5€çï½5€ÕŸ€½5€s÷€I>j0Ô 50ÔUs½5€±€$Ÿ±²+Ä+Ä|I>g€¤Ë€€,€€,€s÷€ÕŸ€ÛºÃô$tP˜ï[æèH˜ïÃ0Ôj+Ä| 50ÔÕŸ€ô$s÷€Éj€ÛºÛº±€ÛºçïÃ¥$[æ=b[æñ€Œa€g€ 5g€j$Ÿj0Ô Ž1-Ãçï= = = Œa€˜–€s÷€[€g€ 5˜–€çïÛº˜–€= €,€g€s÷€€,€7777bBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€0 $’I$’I$’RI$’I$’I$›m¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c­sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUATUUUUUUUUUQUUUUUUUUUUUUUUð `[€[€g€= $ŸI>I>$Ÿ= s÷€[€$Ÿ0Ô[€±€Œa€˜–€UsUsI>0Ô7 ú—€ 5$Ÿj+Ä|= $Ÿ$Ÿ0Ô+Ä|0Ô 5I>s÷€çï1-çïUs€,€s÷€€,€g€½5€˜–€ÕŸ€ÉjI—UÌ[挺I—½5€€,€¤Ë€Éj ޽5€˜–€s÷€Œa Ž[€0Ôjj$Ÿ+Ä|= [€= = = = I>€,€g€€,€s÷€Œa€¤Ë€ÛºY˜–€g€€,€Œa€Œa€s÷€s÷€Éj€±€˜–€Œa€s÷€I>UsI>s÷€€,€€,€[€g€˜–€g€s÷€0Ô$Ÿ0Ô 5j0Ô€,€ÛºÛºÕŸ€±€Œa€ÕŸYÉj€çïô$I—7777ïBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€(0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@UUUUUUUUUUUUUUUUUUUUUUUUUUUUUð aÃYÕŸ€ô$ô$ÕŸ€±€Us= ±²+Ä~7 €0Ô½5€Éj€Éj€ÕŸ ŽÃ=bYÃUÌI—$øÉj€ÕŸ€çïçï Žô$ÛºçïÛº½5€ÕŸ€½5€ÕŸ€çï$ø1-Ã$øUs[€jjj€,€½5€s÷€Ûº1-à Žçï½5€Œa€˜–€[€€,€˜–€[€0Ô0Ô0Ôj 5 5$Ÿ 5jjg€s÷€Œa€= I>I>s÷€g€€,€[€˜–€¤Ë€±€€,€Œa€Œa€˜–€g€¤Ë€s÷€¤Ë€±€s÷€±€˜–€½5€ÕŸ€±€s÷€j½5€±€¤Ë€Œa€½5YÛº½5€¤Ë€g€Us€,€s÷€[€g€˜–€€,€[€gÂ=btPtP€ô$ Ž7777ïBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€@0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ …1Ò¥±®|#)Ò¶¸!¦:¥±®„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUQUUUUTUUUUUUUUUUUDUDUð aYÛº½5€¤Ë€±€ô$UÌUs€,€¤Ë€[€= I>g€Œa€UsŒa€çïÃ[€Us 5+Ä|$Ÿjj0Ô$Ÿg€s÷€Œa€€,€s÷€g€g€€,€[€±€€,€s÷€ 5 5j+Ä~±²+Ä|0Ô= Éj€çïà Žô$Éj€½5€˜–€±€Œa€Œa€Œa€¤Ë€±€Œa€¤Ë€çïô$½5Y˜–€g€s÷€= 0ÔUs¤Ë€Ûº±€Éj€˜–€[€s÷€s÷€s÷€g€˜–€= g€= Us0ÔUs[€+Ä|±²}€…€…ú—‚7 €…ú—‚7 ‚±²~±²~±²+Ä~±²+Ä|+Ä| 5$Ÿg€= j±²|±²~7 €0Ô[€€,€s÷€[€s÷€7777ïBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€T0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUU@UUUUEUUUUUUUð `Usg€[€[€g€€,€[€$Ÿ= [€€,€Œa€I>0Ô€,€= $Ÿ= s÷€½5€½5€Œa€g€Us[€g€¤Ë€˜–€s÷€˜–€Ûº¤Ë€ô$U̘ï€çïÛºŒa$øÛºg€€,€±€çïô$çï±€Œa€¤Ë€çïÛº½5€±€Éj€çï¤Ë€g€s÷€±€¤Ë€$Ÿ±²+Ä~±²~7 ‚7 € 5 5j0Ô$Ÿ 5 5j 50Ôj0Ô 5$Ÿ$Ÿj$ŸI> 5+Ä| 5jj= ˜–€ô$Éj€˜–€= j±²~±²~±²~7 ƒ+Ä|+Ä+Ä| 5jj$Ÿjjj±²~±²+Ä|0Ô0Ô0ÔI>Us0Ô$Ÿj$Ÿ$Ÿ0Ô0Ô0Ô7777ïBUFR&bÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï‚UUUUUUUUU\ç9ε­kZÖµ­kZÖµ­kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷ B„!B‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `= ±€[€I>$Ÿ$Ÿ= $Ÿ±²}ú—ƒ+Ä| 5I>Us= g€½5€[€[€= 0Ô$Ÿ0Ô$Ÿ[À,€Ûº¤Ë€= I>jjUsUs[€$Ÿ0Ô0ÔUs= I>Œa€s÷€¤Ë€ô$ô$YÉj€[€Œa€= ½5€ÕŸ€½5€½5€s÷€€,€Éj€Éj€Œa€Ûºç€UsI>I>€,€UsI>g€Éj€Éj€½5€˜–€g€Uss÷€$Ÿ$Ÿ$ŸUss÷€[€Us[€±Y Ž˜–€Us= j 5I>½5€Éj€Œa€g€g€[€g€s÷€˜–€g€[€Us[€˜–€Œa€€,€s÷€s÷€I>= 5j$Ÿg€g€g€€,€s÷€€,€g€[€7777bBUFR¶bÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¹$’I$’I$’[m¶Ûm¶Ûm¶àŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Êt­®ˆd)Ž„­sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]YŸ dÈ~ð#`€,€çïYUÌ«˜† “à€O€$Ÿ’|%ªˆ¸Ø“à @€0Ô0Ôa¨†  @ 53á@˜–I—1†$øÈ ®` 5j0Ô0Ô$ø @ @j0ÔÃP @“àO€@@±ÏÞV~ˆÈ~ð\À9ûÀgÂ’ÕĬü L¸ q°ã`9ûÀ€,«?Äd?xýà&% ^šÀ½5€’|UÌÄ´ ÓX-P2Z jÏÀÉj’Õ1†¬ü?x øPã`3á@Éj1-$øŸ¼ÈŒ0#`F0À0Ô’|ô$† Ð @ã`3á@€,YŸ dÈÐ @@¤Ë€·UÌc |(³ðI>mÝÕŸ€7777jBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ 0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$¶Ûm¶ÐŠ …1Е-sáN•°!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUEUTUUAUUUUQUUUUð a$ø¤Ë€½5€€,€[€±€ô$Éj€[€€,€€,€g€Œa€ÛºŒa€Us 5 5g€s÷€0Ô= $Ÿ$Ÿ$Ÿ7 € 5j0Ô0Ô 5 5j+Ä+Ä| 5+Ä|jj 50Ô±²~±²|$Ÿ0ÔI>j0Ô0Ô 57 €j+Ä+Ä+Ä| 5 5$Ÿ 5$Ÿ±²}ú—ú—‚±²~7 ú—‚7 ú—ú—ú—sú—ú—sú—ú—€…‚±²| 57 ‚7 ‚±²+Ä~7 ú—€…€Usg€$Ÿj 5 5+Ä| 5j$Ÿ$Ÿú—€js÷€g€Œa€±€Éj€Éj€½5€ô$±€Œa€7777€BUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ40$’I$’I$’II$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†S RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUQUUUUUTUUUUUUPQUð `€,€s÷€€,€±€½5€½5€€,€= 50Ô0Ô7 ‚±²~7 ƒ+Ä| 5jI>0Ô$Ÿ$ŸI>$Ÿ 5$Ÿj˜–€Œa€I>jI>g€¤Ë€ô$$ø1-ÕŸ€g€g€¤Ë€Éj€±€˜–€g€0Ô$Ÿj$Ÿ 5= Us0Ô 50ÔI>g€±€= 0Ô 5+Ä|j$ŸUs[€±€Œa€€,€$Ÿ= = I>0Ô= 5jj$Ÿ¤Ë€s÷€€,€g€Us0Ô+Ä| 5$Ÿ$Ÿ 5 50ÔjjjUs˜–Y˜–€Us= $Ÿ 5 57 ‚7 €±²|+Ä~±²| 5jUsgÂY7777€BUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀH0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUPUUUQEUQ@UUUUUUUUUUUð aâ-‚ 猺I—1-çï¤Ë€s÷€Éj€ÕŸ€Éj€Œa€Usg€Us$ŸI>= Uss÷€Usg€¤Ë€€,€[€ 5±²}€…ú—ú—‚7 ƒ+Ä|[€Œa€[€[€g€I> 5 5 5j$Ÿj 5+Ä|+Ä~±²+Ä}ú—ú—ss€Œa‚±²| 5 5jj±²| 5j 5jj 5+Ä|7 €…‚7 ‚7 €…sú—ƒ+Ä|$Ÿ€,€˜–€¤Ë€¤Ë€¤Ë€±€ÕŸ€Éj€ÕŸ€¤Ë€çï¤Ë€s÷€˜–€g€g€UsUsg€Us= I>g€[€Œa€€,€€,€s÷€I>g€[€¤Ë€˜–€Éj€Œa€UsI>˜–=b€…h Žô$˜–€¤Ë€½5€7777€BUFRöbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ`@"""""""""""#3DDDDEUUUUUUUUUUUVfffffffffffwpŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[%K|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±¯„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUQUTPPU@UTEUUð `Éj€ÕŸ€±€s÷€0Ô$Ÿj= 0Ô$Ÿ= 0Ô$ŸI>g€[€Usg€UsI>Œa€Usj 5 5 5jI>0Ôj 5 5+Ä| 5= $Ÿ±²~±²}ú—s€…ss€…ƒ+Ä|j 5±²+Ä~±²+Ä+Ä~±²~7 ‚7 ‚±²| 5 57 ‚7 ‚±²~±²+Ä~±²~7 ‚7 ‚±²|+Ä~±²|Os€…€…‚7 €jUs 5±²~7 ƒ+Ä~7 ‚7 ‚7 ‚±²}ú—‚±²+Ä| 5+Ä~7 ‚±²~7 ú—ú—€ 5$ŸI>g€s÷€€,€0Ôj+Ä| 5+Ä| 50Ô= [€= = g€= 0Ô7777€IBUFR&bÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÂUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷½ï{ÞðB„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1ŒcB„!@Š2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@AUUU@UUTUUUUUUUUUUUUUUQUUUEUð ` 5$ŸI>[€g€g€g€g€ 5±²+Ä+Ä|±²+Ä|$Ÿ$Ÿ 5±²}ú—€$Ÿ$Ÿ[€0ÔI>$Ÿj 5+Ä}ú—ƒ+Ä|0ÔUs˜–€€,Ø–€[€[€ 5$Ÿ±²| 5s÷1-¥$‚1† ç= 0Ô= 0Ô$Ÿ= I>j$Ÿg€½5€˜–€0Ô= $Ÿ0Ô$Ÿ[€¤Ë€ÛºÉÃŒº˜ïŒºY€,€€,€ÕŸUÌtPI— ŽŒºô}ô} çUÌŒºUÌ Ž¤Ë€[€±€ÕŸ Ž1-ô$±€ 5+Ä| 5j= $ŸI>s÷€¤Ë€j 5+Ä|I>s÷€Uss÷€±€€,€7777bBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUEUUUUPU@UUUUU@UUUUð `UsUs= I>I>I>UsŒa€ÛºI—[æ€Éj€ÕŸ€g€€,€g€Œa€g€ŒaY=bg€$Ÿ+Ä~±²|0Ô$Ÿ$Ÿ€,€€,€= 0Ô0Ôg€j= jjj7 €$Ÿ˜–€[€I>I>UsI>I>Us[€¤Ë€€,€0Ô$Ÿ= 0Ô0Ô7 ‚7 ‚7 ‚7 €…s‚7 ‚7 ‚±²~±²~±²|$Ÿ 5+Ä+Ä|j 5$Ÿ 5±²~7 ƒ+Ä~±²}€…‚±²~±²| 5s÷€˜–€±€¤Ë€g€±€½5€¤Ë€Éj€¤Ë€½5€ÉjY€,€I>= jj+Ä+Ä~7 € 5$Ÿ˜–€½5€±€Éj€½5€½5€Éj€½5€Éj€Éj€Ûºô$ô$¤Ë€7777jBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï(0’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹:V×D2ÇBT·>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUPUUUUUUUUUUUUUUUUUUUUUUPUUUð aY¤Ë€s÷€s÷€˜–€$Ÿ+Ä+Ä~±²|Œa€˜–Y[€[€$ŸUs= 0Ô€,€g€g€½51-[æ€Éj€ 5j 5$Ÿ$Ÿ€,€Ûº½5€˜–€¤Ë€€,€s÷€s÷€Éj€˜–€UsI>= [€Œa€s÷€s÷€¤Ë€ÕŸ€= j= ˜–$ø=bçï½5€€,€g€Œa€€,€ÕŸ€½5€±€½5€˜–€€,€Éj€UsÉj€¤Ë€0Ô0Ô 50Ô0Ô$Ÿj$Ÿj0Ô$Ÿ$ŸI>= Us€,€€,€g€0Ôj0Ôj7 ú—ú—€…€…€…‚7 ‚7 ‚±²~±²+Ä| 5 5$Ÿ$ŸUs¤Ë€¤Ë€±€g€= ¤Ë€˜–€˜–€g€7777jBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠS |#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUTUUUUUUUUUUUUU@Eð `€,€ÕŸ€ô$Œa€[€½5€¤Ë€Œa€g€[€±€± ŽÃÃç€Œa€±€Éj€Ûºô$ô$½5€Œa€g€Us[€g€UsŒa€Us$ŸI>I>g€I>€,€€,€s÷€I>I>[€[€€,€±€Éj€¤Ë€˜–€½5€UsŒa€g€ŒaY Ž¤Ë€Éj1-±€= j 5+Ä~±²~±²| 5I>s÷€[€g€s÷€€,€¤Ë€±€½5€ÕŸ€Ûº¤Ë€¤ËY ޱ€Éj€Œa€¤Ë€[€[€= UsÉj€Ûº˜–€½5€Œa€g€s÷€½5€g€g€€,€€,€s÷€½5€çïô$˜–€g€$ŸjUs 5 5I>€,€UsI> 5+Ä~±²~±²|+Ä|7777jBUFRæbÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏT0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUQU@UUUUUUUTEUUUUUUUUUUUð `$ŸUsI>$Ÿ$ŸUs[€¤Ë€±€Œa€jI>I>jú—ú—ú—€…ú—ú—‚7 ú—‚±²|j= 5I>j+Ä|±²~7 ƒ+Ä|j[€¤Ë€[€$Ÿ$Ÿ+Ä+Ä+Ä| 5 5j$Ÿ[€0Ô$Ÿj0Ô 5 57 ‚±²~±²|I>I>g€Us= Us0ÔI>0Ô= g€s÷€˜–€€,€s÷€€,€[€0Ô±²|0Ô+Ä|[€ÕŸ€ô$½5€˜–€€,€˜–€˜–€UsÉjhh[æ Ž[æ¥$UÌ$øý5€I>Us= 0Ôg€€,€Éj€¤Ë€¤Ë€[€s÷€Usg€[€€,€˜–€¤Ë€±€Œa€½5€€,€Usg€€,€g€I>7777jBUFR&bÿ« fÏ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏUU]kZÖµ­kZÖµ­kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½ï½ï{Þ÷½ï{Þ÷½ï{ÞðŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUTPUUUUUUUUUUUð `= €,€Œa€ÛºYÕŸ€±€s÷€g€= g€Œa€s÷€€,€¤Ë€˜–[ætP€…€…UÌ1-1-YÛºçïçïÉj€ÕŸ€±€[€[€˜–€€,€s÷€Œa€˜–€½5€¤Ë€Œa1-ô}½Ž[æ=bô$ÕŸ€Éj€±€Éj€½5€Œa€Us0Ô[€$Ÿ= 0Ôj0Ô0ÔI>˜–$øÃÕŸ€Œa€ 5+Ä~±²~7 €j$ŸUs0Ô+Ä~±²+Ä|j$Ÿjj0Ô[€Uss÷€˜–€¤Ë€s÷€= = 0Ô= Œa€±€ÕŸ€Éj€˜–€g€Œa€€,€˜–€€,€¤Ë€±€çïçï½5€ÕŸ€ô$ÕŸ€±€½5€Ûº¤Ë€½5€Éj€½5€¤Ë€ç[æ€Ûº½5€7777bBUFRæbÿ« fÏ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUU@QUUUUUUð a$øÕŸ€Œa€±€ÛºÕŸ€ÛºÃ$øÕøâ-˜ïhI—=bYYçï ŽhU̱Y1-±€Œa€= g€g€€,€s÷Ãh‚ ç1†bZçï½5€s÷€Œa€€,€˜–€ÕŸ1-I—¥$èH±Y€Éj€j[€UsI>$Ÿ0Ô 5˜–½Ž€±€s÷€Éj€Ûº±I—Ûº˜–€Œa€ÛºÃUÌtPY0Ô+Ä|jjj= s÷€˜–€s÷€˜–€˜–€ÕŸ€˜–€s÷€[€$Ÿj0Ô$Ÿ0Ô$Ÿ[€g€ 57 ‚7 ‚7 €7 €j¤Ë€Œa€±€½5€€,€¤Ë€ô$1-1- ŽYY±Yâ-‚V%tP€ÕŸ€±€±€Éj€½5€Ûº½5€€,€7777ïBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@0’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹:V×D2ÇBT¶9ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUTUUUUUUUUUUUUUUUUUð a=b çñ€˜–€€,€$Ÿ 5±²|0Ôs÷€˜–€˜–€s÷€[€I>$Ÿ0ÔUss÷€€,€s÷€½5€½5€ô$h[æ Ž1- Žô$ÕŸ€çï Ž ŽÉj€Œa€˜–€g€g€Œa€g€€,€g€[€g€Usj$Ÿ 5±²}ú—€±²|0ÔÛº$ø ŽÕŸ€g€Œa€[€Us[€[€g€±€½5€Ûº1-[ætPhUÌÃÉj€±€0Ô 5s÷€s÷€ÕŸ€Œa€$ŸjI>Us[€UsŒa€ô$À…=b±€½5€¤Ë€½5€ÕŸ1-çï±€s÷€[€[€g€Œa€€,€½5€˜–€s÷€€,€s÷€çï½5$øI—ŒºI—Œº€çï$Ÿ±²| 5±²|7777ïBUFRöbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@0@DDDDDEUUUUUUUUUUUVfffffffffffgwwwwwwwwwwwxˆˆˆˆˆˆˆ€ŠB˜èJ–ƹðŒ§JÚà†B˜èkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUTUQUPUUUUUð b7 ‚7 €j±²|[€˜–€€,€= [€Us= 0Ô0Ô0ÔUs˜–€ÕŸ1-1-Yg€g€jjjg€½5€ô$$øg€[€g€˜–€±$ø€…€…Ã1-çïŒa€Éj€s÷€UsUs˜–€çï½5€Éj€€,€= Us0ÔI>I>Us[€½5€±€çïÉj€±€±€[€I>$Ÿ±²|jUs$Ÿ+Ä|+Ä+Ä|+Ä| 5$ŸjI>$Ÿ 5±²~±²+Ä|±²~7 ú—€…ú—‚7 ƒ+Ä|j$Ÿg€= ˜–€½5€€,€g€[€g€Us 5+Ä~7 s€Œa€Œaú—€0Ô0Ô˜–€[€g€[€g€˜–€Œa€½5€7777€±BUFRöbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï@P@"""""#33333333333DDDDDDDDDDDDUUUUUUUUUUUUffffffffffffwwwwwwp‹Êt­®Æ¹ðŒ§JÚà†B˜èJ–ƾ”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUPUUUU@UUUUUUUUUUUUUUUUPUUð a1-[æÃÛºçï½5€[€= Œa€˜–€€,€¤Ë€¤Ë€[€¤Ë€½5€±€¤Ë€€,€0Ô 5$Ÿ7 ú—‚7 €UsÛºYÕŸ€˜–€Œa€¤Ë€g€Œa€±€±€Ûº½5€Ûº±€¤Ë€s÷€ 5 5j7 ú—ƒ+Ä|UsÕŸ€Ûºs÷€˜–€˜–€¤Ë€[€¤Ë€˜–€±€½5UÌô$ô$à Žñ€I> 5 50ÔI>Éj€ÕŸ€½5€±€s÷€¤Ë€½5€ÕŸ€±I—I—htPI—UÌçïŒa€±€½5€ÕŸ€±€I>= $Ÿ[€€,€I>0ÔjI>s÷€0Ô= 0ÔI>ÉjI—=bY½5€I>7 €Œa€…s‚7 €$Ÿ½5€ô$±€¤Ë€¤Ë€s÷€¤Ë€7777€±BUFR&bÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏBUUUUUUUUUUU]kZÖµ­k[Þ÷½ï{Þ÷½ï{Þ÷½ï|ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷ B„!B„!BŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUTUUUUUEUUUU@UUUUUPUUUUð `€,€¤Ë€½5€Ûº Žô$ÕŸ€çïÉj€±€s÷€I>= ±²}ú—‚7 ƒ+Ä|g€Œa€¤Ë€s÷€Usg€s÷€UsÉj€Éj€Éj ŽÉj€s÷€= $ŸjUs+Ä+Ä~7 ‚±²|I>±€çï½5€g€½5€±€€,€g€¤Ë€¤Ë€˜–€½5YÕŸ ޽5€ÕŸ€ 5jj+Ä|jj1-[æYô$ÕŸ€Œa€¤Ë€˜–€Éj€Œa€¤Ë€¤Ë€±€˜–€[€[€$Ÿ+Ä}€…ú—‚7 ‚7 ƒ+Ä|js÷€¤Ë€¤Ë€¤Ë€€,€Œa€g€I>[€I>Us˜–€€,€g€0Ô0Ô 5 5 5jI>7 ú—€$Ÿ0Ôg€0Ô$Ÿ 5j0Ô 5$Ÿ$Ÿ0Ô€,€g€[€½5€7777bBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS c\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðU@QU@UUUUUUUUUUUUUUUUUUUUUUUUð `= [€ 5= 0Ô+Ä}€…‚±²}€…€…€…‚7 ‚7 €…‚±²|j+Ä|$Ÿ= I>= 5+Ä}€…€Œa‚7 ú—ƒ+Ä|$Ÿ¤Ë€çïÃÛºÛº¤Ë€Œa€s÷€€,€±€ÛºçïY ޽5Ã1-1-ÃÕŸ€Ûº¤Ë€˜–€€,€¤ËñYÉÀ՟€çïÕŸYÃh˜ï±Y€…â-‚²¥$[æ=bUÌô$½5€ÉjY[æâ-â-Œº[怱€Éj€ÕŸ€±€ô$I—½ŽÉñYâ-¥$[æUÌçïô$±€€,€s÷€˜–€Ûº1-Y$ø ŽÃYçïçïô$=bUÌI—=bYÛº€,€[€I>I>0Ô0Ôj0Ô˜–€7777BUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€ 0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUU@UUUUUUUUUUUUUUð `½5€Ûº±€¤Ë€±€Œa€€,€Œa€Éj€ÕŸ€Ûºô$[€˜–€s÷€I>= 0Ôg€$Ÿú—€j+Ä+Ä|0Ô= = [€g€UsI>g€Œa€Éj€½5€s÷€g€¤Ë€ÕŸ€çïÕŸ€€,€Usg€= j 5 5[€s÷€€,€Us+Ä|j+Ä+Ä|j0Ôj[€ 5$Ÿ±²+Ä~7 ‚7 €Œa€ÛºÕŸ€½5€¤Ë€˜–€I>I>Uss÷€Œa€çïÃ1-$øô$ Žçïçïçï Žô$ÕŸ€ÕŸ€ÉjÃ=btP1-Éj€s÷€˜–€çïÕŸ€Ûºô$1-[挺ô}ô}±Y˜ï€…I—Ûº˜–€[€½5=bÕøô}IðÉÀçïÕŸ€˜–€½5€7777BUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€40I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUDUUUUUUUUUUUUUUUUTUUUUUð `ô$U̘n½ŽŒºÕøÉÃtP$ø ŽçïçïÉj€Ûº=bô}±²‚Õø€½5€g€€,€[€Œa€Éj€½5€±€¤Ë€¤Ë€˜–€g€[‚±²|$Ÿss€…€jI>˜–€€,€˜–€±€±€˜–€s÷€Usg€Œa ŽÃÃçïÉj€s÷€±€g€Us0ÔI>s÷€¤Ë€±€±€Éj€½5€[€= = [€¤Ë€ÕŸ€ÕŸ€Éj€ÕŸ€ÕŸ€Œa€€,€Œa€€,€Œa€½5€Œa€s÷€s÷€Œa€¤Ë€€,€g€[€I>I>I>Us0Ô= Usg€˜–€Œa€Œa€UsI>$Ÿj±²|jI>g€[€0Ôj 5 5 5 5j= [€Œa€Œa€€,€Us= I>7777BUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€H0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶í¶Û`‹pC!Lt-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðDUUUTUUUUUUUUUUUUQUUUUUEUUUUT@ð `j+Ä|7 ú—‚±²|j0Ôg€I> 5 5 5$Ÿ= Us0Ô0Ô$Ÿ$Ÿ 5+Ä| 5j$ŸI>g€s÷€Us$Ÿ$ŸI>I>g€s÷€±€½5€Éj€±€±€˜–€Œa€g€I>0Ô= jjj= g€s÷€[€g€€,€s÷€¤Ë€½5€½5€½5€½5€½5€½5€½5€½5€çïçïŒa€0Ô+Ä|$Ÿ˜–ÃYÕŸ€±€g€s÷€Œa€˜–€½5€ÕŸY½5€±€˜–€¤Ë€¤Ë€Ûº½5€g€= +Ä|jI>[€g€= s÷€= 0Ô[€[€g€g€g€Œa€˜–€Ûºs÷€= jj7 € 57 ƒ+Ä~7 €…‚7 ‚±²|j7777BUFRæbÿ« fÏ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï€`0I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUUUUUUUUUUUUUUUUUUUUUUUUUUð `$Ÿj 5jŒa€g€s÷€Éj€Éj€= = = I>g€0Ôú—‚7 ‚7 ú—‚±²|= ±€çïçï½5€±€Éj€Œa€s÷€s÷€˜–€çïÛº Žô$$øYÕŸ€Œa€€,€Us$Ÿj[€˜–€½5€Ûº€,€€,€Œa€˜–€s÷€±€½5€ô$YYô$Yçïô$YÛºÉj€g€[€s÷€˜–€Éj1- ŽÉj€Ûº¤Ë€½5€˜–€±€ÉjY ŽÃô$ô$½5€Œa€Œa€j 5j0Ԥˀۺ1-1-Ã$ø Ž Ž1- ŽhI—tP€…tP[æ[æh[ætP$øô$çïÕŸ€ÛºÛº½5€¤Ë€¤Ë€±€ÕŸ Ž=b1-UÌhI—7777BUFR&bÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï‚UUUUUUUUUUUUUUUUUU^sœç;Þ÷½ï{Þ÷½ï{Þ÷½ï}ï{Þ÷½ï{Þ÷½ï{Þ÷€„!B„!B„!„!B„!B„!BÆ0‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±¯„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUPUUU@UUUUUEUUUUUUUUUUUð aÃô$=btPh[æ[ætP$øô$Éj€Éj€¤Ë€g€Œa€˜–€€,€g€g€Éj€g€g€gÂY¤Ë€˜–€€,€Us[€= +Ä+Ä}ú—ss€…ú—€g€ 5$Ÿj0Ô0ÔUs¤Ë€s÷€€,€g€Us[€0Ô+Ä}ú—‚7 ss€…‚7 €I>˜–€ÕŸ€½5€¤Ë€¤Ë€ÛºÉj€½5€Œa€Éj€[€[€çï¤Ë€€,€= j 5+Ä|jUsI>s÷YÉj€€,€= I>[€[€±ÃI—[æhhUÌô$Œa€I>= 0Ô= [€çï$ø[æÃ Ž€,€Éj€ô$ ŽI—I—[怅Œºh ŽYÛº¤Ë€s÷€Us7777bBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTUUUUUUUUUEUUUUUUUUUUUUUð `g€= g€ۺçïà ŽçïÉj€±€½5€ÕŸ€½5€çï ޱ€±€˜–€¤Ë€s÷€I> 5 5±²~±²~7 ƒ+Ä|$ŸUsŒa€€,€s÷€[€UsÉj ŽÃYÕŸ€±€g€I>$Ÿ+Ä~±²+Ä~7 ‚7 sú—‚7 €j= $Ÿ0Ô= 0Ô$Ÿ= [€± Žô$ÕŸ€Éj€Œa€˜–€Us= +Ä|0Ô±€Éj€Éj€ÕŸ€½5€˜–€±Y½5€ÛºÃ$øYY Žô$YYÛº€,€[€j0Ô½5Ã$øô$ô$YY Ž$ø1-=b=b$øYô$ÛºÕŸ€çïÛºYçïô$ÛºÛºYÃô$ÛºÕŸ€7777æBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ$0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUPUUUU@UUUUUAUUUUUUUUUð `çïÉjYÃÃI—UÌUÌI—=bUÌI—UÌ=bUÌ$øÃô$çï Ž=b[æ[æYô$ Ž$ø1-Ã=bI—ÃÉj€˜–€[€[€= 5+Ä~7 ú—‚7 €s÷€Ûº=bÃ Ž Žçï€,€¤Ë€ÛºYô$Éj€¤Ë€¤Ë€½5€±€€,ƒ+Ä+Ä~7 ú—‚7 ƒ+Ä|[€½5 Ž$øô$€,€Us€,€±€˜–$ø$øÃ$øçïçïÉj€ÛºÛºÕŸ€g€±²+Ä|I>ÕŸ€Éj€ÕŸ€Éj€Éj€ô$ÕŸ€˜–€¤Ë€˜–€±€s÷€¤Ë€˜–€½5€Éj€±€¤Ë€±€˜–€s÷€= j0ÔUsUsI> 5 5jj= ˜–€Éj[æUÌ7777æBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀ80’I$’I$’I)$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUQUUUUQUUUUUEUUUUUUUUUUUð `ô$±€½5€Ûº˜–€€,€¤Ë€€,€Œa€˜–€ÕŸ[æÉ‚Ið€…YUÌtP[æ¥$€…ŒºtP[æ Ž Žô$çï½5€€,€0Ô$Ÿ±²|g Žô$ÛºÛº¤Ë€±€ô$hhh[æ=bçïs÷€I> 5+Ä| 5[€± Ž1-Ãô$ÕŸ€Ûº±€ÕŸ$ø€…˜ï˜ïtPI—=b ŽÉj€˜–€j7 €$Ÿs÷Y[æ˜ïUÌÃÛº¤Ë€€,€¤Ë1-Ã Ž¤Ë€ÕŸ€ÕŸ€s÷€s÷€0Ô+Ä|+Ä|= I>˜–1-[æÃô$ÕŸ€¤Ë€±€½5€ÛºÛºô$Ûº½5€½5€¤Ë€¤Ë€Œa€€,€0Ô$Ÿj$Ÿ7777æBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀP0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUPUUUUUUUUUUUUUUUTUUýà`= s÷€¤Ë€½5€½5€˜–€s÷€€,€€,€Œa€±€ô$ ŽÛºÏ…Éj€±€¤Ë€€,€OX€Œa€s÷€g€OX€[€g€€,€½5€˜–€˜–€¤ËY˜–€çïçïô$YYô$ô$ÃÃYô$Œa€+k‚¥}|= ½5€Éj€ÛºçïÏ…±€±€çïô$Ã$øÃ Ž=bŒºh$øYYô$Ï…±€½5€˜–€Éj€Ï… Ž1-Ï…çïçïçï ŽhhtP[æhI—YÛº[€[‚¥}~+k‚¥}}îb€OX€Éj ŽÃÏ…¤Ë€€,€s÷€±€Ï…½5€˜–€g€[€˜–€g€j¥}~+k€ú>îb‚+k€jI>Éj1-=bY ŽÉj€7777æBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏÀd0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS c\øFS¥mpC!Lt%Kc_Êt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUUUUUUUUTUUUUUUUUUUAð `½5€ÛºI—ÃUÌô$˜–€= €,€Us$Ÿj 57 s€Œaƒ+Ä|0Ôs÷€Éj€¤Ë€€,€Œa€€,€˜–€¤Ë€±€€,€±€[€ÛºYUÌUÌäˀg€Œa€€,€j€,Y$ø±€ÕŸ€˜–€±€ô$YYÕŸ€ô$€,€€,€I>0Ôj±²~±²}€…€Œa€Œasƒ+Ä| 57 €0Ô0Ôj$Ÿ= jj 5+Ä~±²~7 ú—‚7 €$Ÿ€,€½5$øI—h€…tPUÌI—[æUÌh[挺‚ô}½Žh1- Žô$Éj€s÷€I>½5€çï ŽÛº½5€¤Ë€Œa€s÷€¤Ë€±€g€Œa€[€ 5+Ä+Ä|7777æBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUUUUUUUPUUUUUUUUUð b7 ‚7 €…‚7 ‚7 €…€0ÔÉj$øñ€s÷€I>I>I>Us¤Ë€çïô$½5€[€[€= +Ä}€…ú—s€Œasú—€$ŸÛº=b1-ô$¤Ë€€,€˜–€Éj$ø$øÛºÕŸ€½5€ÕŸ€s÷€7 €ú—sss‚7 €j[€0Ô 50Ôj 5UsŒa€½5€[€s÷€g€€,€Œa€€,€$Ÿ+Ä~±²~±²+Ä|j[€±€ÕŸ€[€I>0Ô0Ô= = [€˜–€s÷€Œa€˜–€g€€,€$Ÿj 5±²}€…ƒ+Ä|±€±€Œa€Œa€s÷€Œa€Œa ŽÃ ŽYYÕŸ€½5€˜–€g€ 57 ‚7 ú—€…ú—‚±²|= ˜–€7777æBUFRæbÿ« fÏ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUU@UUUUUUUUTUUð `Éj€¤Ë€s÷€Œa€s÷€I>€,€s÷€± ޱ€Us= = j 5+Ä|7 ‚±²|$Ÿ0ÔÉj€çïUÌ=bÉj€Ûºs÷€¤Ë€½5€€,€Éj€ÕŸ€Ûº Ž=b€…€ÛºUs= j= j 5jŒa€ÕŸ$øô$½5€Éj€½5€Éj€˜–€Ûºç€¤Ë€Éj€¤Ë€½5€g€0Ô 5ú—ú—ú—€…ƒ+Ä|0Ôg€½5€¤Ë€Œa€˜–€Œa€˜–€¤Ë€½5€ÕŸ€çï ŽÉj€˜–€Éj€Us 5€…‚7 ú—ú—ú—€ 5[€ô$$ø1-I—1-ô$Ã1-ŒºtPhI—YÕŸ€0Ôj$Ÿ$Ÿg€j±²~7 ‚±²|Us˜–=bh1-ÕŸ€s÷€g€Œa€Œa€7777æBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ï,0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTUUUUUUUUUUUAUUUUUUUUUUTð `= I>g€I>I> 5 5$Ÿ±²|ú—‚±²~7 ú—‚7 ú—€= [€g€g€g€s÷€˜–€¤Ë€g€I> 5j 5 57 ‚7 ƒ+Ä~7 ƒ+Ä|j$Ÿ±$øI—hI—1-I—$øUÌUÌI—=b Žô$çï=btPUÌI—=bÃÛº[€0Ô€,€ÉjY$øÛºYÃ[怅€…tP[æY€,€Us0Ô€,€Œa€j+Ä+Ä|I>ÕŸ€ÕŸ€ô$=b1-=bçï½5€ÕŸY ŽI—=b=b=b[æ=b1-çïs÷€= I>[€€,€¤Ë1-1-Ãçïô$ÛºçïY$ø=b=bUÌÃÕŸ€¤Ë€¤Ë€I>0Ô+Ä|7777æBUFRæbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏD0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUTUUUUUAUð a€…ss‚7 €0ÔŒa€˜–€ÛºÛº€,€½5YÛº1-=b[æI—=bô$çï ŽçïÉj€Ûº€,€s÷€Ûº$ø1-hÉÂV%%QÕø¥$€…h[æI—=bI—I—tPtP=bÃ$øI—=b1-Éj€g€= Us[€= g€g€s÷€g€s÷€½5€±YÕŸ€çïÛºÃ=b Ž$øçïÕŸ€çï Ž1-hÉÂ1†²²ô} ç çÉÃ¥$[æI—1-I—I—1-=b1-UÌUÌ Ž= j+Ä|$ŸUsÉj€ÕŸ€çïçïÛºYÃÃçï$øçïçï±€s÷€Usg€= $Ÿ 5+Ä~±²|Usg€Œa€g€7777æBUFRæbÿ« fÏ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏX0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!§BT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUPUUUEUUUð `[€s÷€s÷€g€g€s÷€€,€s÷€[à Žý5€Us0ÔI> 5j$Ÿ€,€½5€Ûº±€˜–€˜–€±€˜–€½5€ÛºçïŒa€Us0Ôj+Ä}€…€…‚7 ú—ú—ú—ú—€$ŸUsYÃ1-ÕŸ€ÕŸ€çïŒa€0Ôj$Ÿ7 ‚7 €7 ss€…€…€…€…€Œa€Oú—‚±²|+Ä|ú—€…s€jI>±€ÕŸ€Us+Ä~7 ú—€…s€Œaƒ+Ä| 5+Ä+Ä|7 ƒ+Ä|0Ô0Ô0Ô[€s÷€Œa€= 0ÔUs±€ 5ú—s‚±²|j0Ô±²|jŒa€ô$1-ÉjÃY Ž ŽYÃI—±Y€…€7777æBUFRfbÿ« fÏ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÏUUUUUUTD»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»°]kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷¾÷½ï{Þ÷½ï{Þ÷½ï{À!B‹:V×D2ÇBT¶5Ï„e:V×D2ÇBØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUAUUUUUUð a=bI—1-çïYÕŸ€˜–€€,€$Ÿ 5= [€s÷€g€±€Éj€çïÉj€ô$$ø1-I—UÌ1- ŽÉj€ô$¤Ë=bÕŸ€ÕŸ€Éj€Éj€ÕŸ€ô$Y½5€ô$Éj€ÕŸ€ÛºÃ1-=bhUÌ$øÛºÕŸ€½5€½5 ŽÛº¤Ë€[€s÷€½5€ÕŸYô$ô$ÛºçïYÃ[æ=bUÌ[æh1-1-$øÛº½5=b$ø ޱ€½5€ô$çï Žô$ô$ ŽÃ Žô$ô$ Žô$Éj€ÕŸ€ÛºÕŸ€ÕŸ€±€g€€,ƒ+Ä~±²|jUsçï ŽY1-ô$ÃYÛº$ø=bŒºh$ø1-I— Žô$s÷€[€[€$Ÿj7777BUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUUUUUUUUUUUUPUUUUUQUUð `g€¤ËÃY Ž1-ÛºÕŸ€ô$ô$ÕŸ$øŒa€UsI>g€g‚±²}€…s€Œa€O€Os‚±²|j+Ä|[€UsI>g€¤ËÃI— ŽÛº=b1-ô$çïÕŸ€ô$YUs= g€s÷€Éjhh½ŽI—YÛºÉjY[€s÷€Éj€ÕŸ€ô$YÃI—çïÉj€s÷€0ÔUsI>0Ô$Ÿ¤Ë€ÛºÃ1-ÛºÕŸ€ÛºÕŸ€¤Ë€¤Ë€˜–€±€I>$Ÿ+Ä~±²~±²}ú—ú—€Os€…€O‚7 €js÷€Ûº Žçï½5€½5€¤Ë€±Ã=btP€…€…˜ïÕø˜ï$øçï[€0Ôj7 €I>ÛºÃô$YÕŸY¤Ë€7777 ŽBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶ÛrI$’I$’I%¶Ûm¶Ûm¶ÛnÛ`ŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[%:V×D2ÇBT·>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUUUUTUUUTUUUTUð `€,€½5€ô$ô$ÕŸ€ÕŸ€˜–€€,€g€gƒ+Ä+Ä~7 ú—s€…€js÷€Éj€Œa€g€I>= = [€¤Ë€½5$ø ŽYÛºYI—Y€,€€,€g€= Us[€€,€ÛºI—$øÛº˜–€g€Uss÷€Œa€ô$[æhhŒºŒºhI—ô$çïÕŸ€ÕŸ€½5€ô$YI—hhUÌI—=b1-YYYÕŸ€Éj€$Ÿ±²+Ä+Ä|$Ÿ½51-çï±€½5€˜–€Éj€¤Ë€ÛºÉj€±€Œa€Œa€g€j7 €…ss€…‚±²|0Ԥˀô$YÛºÛº Žô$ÛºÛºÛºçï½5€˜–€I>I>j 5+Ä| 50Ô0Ô7777 ŽBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@40$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUDUUUUUUUUUUUUUUUUUUUUð ` 5s÷YI—h ŽYô$ô$Ã=b€…tP¥$¥$€…hUÌ$øÛº˜–€€,€Usg€˜–YI—[æ[æ ŽÛºçïÃYY½5€½5€€,€g€g€UsI>0Ôj±²|+Ä|$ŸI>€,€¤Ë€±€±€s÷€s÷€½5€½5Ã=bà Ž1-1-1-=bçï€,€UsI>0Ô€,€Éj€ÕŸY ŽY±€ÛºÕŸY ŽÃ1-1-YÃô$Ûº€,€= 0Ô$Ÿ€,€$ŸUss÷€˜–€ÛºYÕŸ€ô$Y Žô$Y1-UÌI—I—I—1-ô$ÛºUs˜–€[€½5€¤Ë€Œa€½5€Éj€Ûºô$Ûº Žô$7777 ŽBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@H0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUPUUUð a Ž$øI—1-$øô$Éj€ÕŸ€±€˜–€€,€s÷€½5€ÛºçïÛºÛºYçï=bÃY$øYÛº½5€ÛºI—˜ïô}%Q ‚ çâ-hI—UÌ[æÃYYYÃô$ô$ô$ô$±€½5€ô$$øÃ=b1-1-$øI— ŽçïÛº±€s÷€˜–€Éj€ÕŸ€ÕŸ€ô$Ûº½5€ÕŸ€ÛºÛºô$1-1-=b=bUÌÃs÷€0Ô$Ÿ±²~7 €O€Œa€Œaú—€= I>0Ô$Ÿ[€s÷€UsUs€,€±€±€±€Œa€[€0Ô0Ô 5= 5+Ä~±²}ú—‚7 €0Ô0Ô$Ÿ= = Usg€g€€,€˜–Yçï Ž Ž7777 ŽBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@\0$’I$’I$’JI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹[\ÈS RØ×>”é[\ÈS RØçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU@ð `ÛºÉj€½5€ÕŸ€çïÛº½5€s÷€Œa€çï Ž1-1-çïà Ž$øÃ1-UÌÉÃŒº±YèH¥$hI— Žô$YçïÕŸ€ÕŸ€ô$=b€…â-‚¥$=b$ø$øhŒº[æ1-1- Žô$ô$ô$à Ž$øÃô$ Žô$Ãà Žô$1-UÌI—[æ$ø$ø Ž ŽYÛºçïÕŸ€çïÛºÉj€Éj€ÛºçïY Ž$ø$ø$øÃ$øô$Y1-$øI—I—$ø$ø1- ޽5€˜–€s÷€= Us$Ÿ$Ÿ[€ÕŸ€çïÉj€¤Ë€¤Ë€˜–€˜–€½5€¤Ë€Œa€€,€s÷€Us= j$Ÿ 5j€…€Œa€Œa€7777 ŽBUFRVbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐBUUUUUUUUUUUUUUU^sœç9Îsœç9Îs½ï{Þ÷½ï{Þ÷½ï{Þ÷Þ÷½ï{Þ÷½ï{Þ÷½ïx!B„!B„!B„B„!B„ Šc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð„ B€€B„!B„!BB„!B„!B„!B„!B„!@B„!an6tÿtþŸcŸcŸcŸctÿtÿ“†ü€,€g€g€€,€gƒtÿtþŸcŸc“†ÿtþbZô$n6tü˜–€½51-±ƒ“†ÿ“†ÿtýèHbZŸctÿtÿtýèHŸcèHn6èHô$zzzbZ¤Ë=bC| ŽÃ Ž1-C|[æ1-Y=bYÛº½5€½5€¤Ë€gƒ“†þbZbZèHtüs÷€çï$øÃçïô$ ŽYYC|O±ŒºO±Ã$øÃÃý5€±€g€Œa€¤Ë€çïY=b[æO±Yçï½5€ÃPçï Ž Žh=bYô$ô$ô$¤ËƒtÿtþbZ“†ÿtü½5$ø¥$齎܌ºtPO±€7777ŸBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ 0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[ŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUPUUUQUUUð `çïô$Y=b1-YÕŸ€€,€¤Ë€g€+Ä~7 ‚7 €$Ÿs÷€±€½5€±€Œa€Éj€Éj€±€Éj€½5€Éj€ÕŸ€€,€€,€s÷€0Ô= j+Ä|7 ú—ƒ+Ä|$Ÿs÷€UsUsUsUsUs[€±€½5€çïçï±€½5€g€I>0ÔI> 5±²~±²}ú—‚7 ƒ+Ä|0Ôg€I>I>[€UsUsUs0ÔUs[€Usj±²}ú—€…€…€Œa€…s€…‚±²|j¤Ë€ô$ÛºÕŸ€¤Ë€±€€,€s÷€[€€,€g€[€= j+Ä|€…s€Œa€…‚7 ú—ú—ƒ+Ä|I>¤Ë€¤Ë€¤Ë€[€$Ÿ$Ÿ$ŸjUsj±²~7 ‚7 s€7777a€BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ$0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUUUUUUUUPUQUT@EUUUUUUð asú—€Œa€…s‚±²|0ÔÕŸ$øô$½5€s÷€s÷€0ÔI>€,€ÕŸ$øÉj€çï±€Éj€s÷€I>7 ‚7 €…s‚7 €jI>Us€,€Œa€˜–€[€I>= Us¤Ë€çïÃY=b€…h€çïUs= I>0ÔjUs±€çïYYY€,€g€s÷€€,€±€½5Yô$Ûº½5€Éj€[€Us= ±²}ú—s€…€…ú—€$ŸUs0Ô 5 5j+Ä| 5€,€½5€ÕŸ€g€I>+Ä| 5+Ä~±²}ú—€ 57 € 50ÔI>0Ô 50Ô$Ÿ$Ÿ[€¤ËÃI—[æ[挺tPtP[æ=b=b=b ŽY$ø[æ€7777a€BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ80$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ„©q”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUTUUUUUUUUUUUPUUUTUUUUð aUÌ ŽYÃ1-$øI—[æ Ž€,€[€j$Ÿ 50Ô[€ÛºtPUÌ[æÃÕŸ€ÛºYY ŽI—I—ô$˜–€g€$Ÿ$Ÿj±²~7 ‚7 ú—‚±²| 5$Ÿ˜– ޽5€[€0Ôjj0Ô= s÷€Éj€€,€[€I>g€ۺ˜–€±€g€Us$Ÿ= €,1-=bÃUÌ ޽5€s÷€€,Y€…UÌ Žçï¤Ë€I>g€€,€$ŸUs€…‚7 ƒ+Ä|Usô$Y Ž˜–€s÷€= = 0Ô= [€[€I>0Ô€,€= 5€…ƒ+Ä| 5 5$Ÿ[€s÷€¤Ë€g€[€˜–€Éj€s÷€Œa€Œa€ÕŸ€çïçï=bUÌ7777a€BUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ЀL0$’I$’I$’JI$’I$’I$›m¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹[\ÈS RØ×>”é[\ÈS RØ×>•+k€" c¡*[\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUPUUUUUð a[æ[æI—1-$ø$øô$ÕŸ€½5€±€ô$ Ž$øYÕŸ€€,€ÕŸ€±€¤Ë€˜– ŽI—YÛºÛºÉj€½5€s÷€I>I>jj[€Œa€ô$1-Ûº€,€s÷€s÷€g€½5€±€ô$€…±Y¥$ŒºÉñY˜ï[æ$ø$ø$øUÌ1-tPâ-I—=b ŽÉj€¤ËYUÌtPtP=b Ž=b1-YÛº±€s÷€€,€€,€¤Ë€ÕŸ€çïÃçï±€±€€,€±€˜–€¤Ë€½5€Ûºçï½5€½5€Œa€g€0Ô+Ä}ss€…€$Ÿ¤ËtP˜ïUÌÕŸ€çï±€Œa€ÕŸYUÌI—=bçï±€¤Ë€g€= j$Ÿj±²|I>˜–€7777a€BUFR&bÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ЂUUUUUUUUUUUUU\cÆ1ŒcÆ1Œg9Îsœç9Îsœç9ÎsœëZÖµ­kZÖµ­kZÖµ­o{Þ÷½ï{!B„!B„!BˆB„!B„ Št%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUPUU@UUUUUUUUUUUUð `ô$YÕŸ€¤Ë€˜–€Us0ÔI>s÷€¤ËY[æ¥$€…[æ=bYÃÃô$Œa€= UsŒa€˜–€¤Ë€½5€g€j= = g€s÷€¤Ë€˜–€Us= jj 5+Ä+Ä|€…€…€…€…ú—‚7 ‚7 ‚7 ‚±²| 5+Ä+Ä| 5$Ÿ$Ÿ 5j 5$Ÿj7 ‚7 ú—ú—‚±²|0ÔUsŒa ŽÉj€Œa€½5€Éj€Éj€ÕŸ€Éj1-$øÃ$øÛºÉj€Éj€˜–€UsÛºý5€[€€,€½5€ÕŸ ŽÕŸ€±€±€Œa€±€çï±€¤Ë€½5€€,€UsUs0Ôj+Ä}€…ú—€…ú—s‚±²|= Y$ø¤Ë€Œa€g€Us= €,€7777ÿBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀ 0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUEUUUU@UUUUð `s÷€¤Ë€¤Ë€˜–€¤Ë€˜–€€,€g€UsUs[€g€g€I>s÷€½5€çïô$±€€,€Usg€[€UsUss÷€Œa€çïUÌ ŽÛºÕŸ€ô$€… Ž ޱ€¤Ë€ÕŸ€ô$Éj€ÕŸ€¤Ë€s÷€I>$Ÿ$Ÿ= I>= $Ÿg€çïŒa€[€UsŒa€0Ô$Ÿ±²~±²|jI>ÛºÃÃÉj€±€s÷€[€s÷€g€˜–€Ûº1-ÉjYg€Œa€Us0Ô 5 5 5±²|$Ÿg€՟€¤Ë€Éj€s÷€= s÷€I>[€˜–€½5€Œa€Ûº½5€g€g€0Ô7 ‚7 ú—€…€…€…ƒ+Ä|I>g€Œa€±€g€Us= 0Ô$Ÿ$Ÿ= = 0ÔI>$Ÿj7777sBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀ 0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUU@UUUUUUUUUUUUUUUUDýàc~+ktPîbtP€ú>€ú>ƒ|g€s÷€OX€I>0ÔI>[€±€€,€½5€çï¤Ë€€,€[€[€0Ô0Ô$Ÿ$Ÿ[€˜–€½5€Ûº˜–€Éj€€,€Œa€s÷€s÷€[€[€[€[€[€g€OX€= I>= j~+k‚+kîb€ú>€ú>îb€ 5j$Ÿ0Ô$ŸOX€I>OX€[€Œa€ÛºÏ…À…€Ûº˜–€€,€˜–€OX€[€0Ô 5 5€,€[€j 5j 5 5$Ÿ$Ÿs÷€¤ËÃ1-1-$øY¤Ë€€,€€,€I>I>[€s÷€±€Ï…Éj€˜–€½5€¤Ë€±€€,€¤Ë€çï Ž˜–€[€= = s÷€0Ôîb€ 5+k‚+k‚+kîbƒ|7777sBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀ80’I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÐŠt%Kc\ùÒ¶¸!¦:¥±®|#)Ò¶¸!¦:¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUQUUUUUUUUUUUUUUUUUU@UUUUUUUUUð `[€˜–€¤Ë€[€s÷€[€0ÔI>g€˜–€g€[€= j+Ä| 5g€çïUÌÃçï€,€s÷€I>= g€g€€,€ÛºŒa€g€€,€€,€s÷€s÷€g€½5€$ŸjjI> Ž$ø ŽÛºÕŸ€Éj€½5€ÛºÛº1-1-=b=bYô$€,€UsI>js÷€g€Uss÷€çï1-1-1- ŽÃÃÃ$øÃÃô$¤Ë€½5€ÕŸ€Éj€˜–€¤Ë€€,€s÷€g€UsŒa‚7 ‚±²|$Ÿg€g€I>= 0ÔI>€,€Éj€ô$h˜ï ŽÕŸ1-ô$±€ÛºÃ$øÃà Ž1-1-Ãs÷€€,€s÷€s÷€I>$Ÿ0Ô0ÔŒa€7777sBUFRÖbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!‚LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀL@"""""333334DDDDDDDDDDDEUUUUUUUUUUUVfffffffffffgwwp‹:V×D2ÇBT¶5Ï„e:Zà†B˜èJšçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ aY Ž$ø1-$ø ŽçïÃP¤Ë€˜–€€,€¤ËÃŒº‚ çÏÞYÛºYY1-O±Œº[æ[æC|1-C|O±=b Ž Ž$ø=bO±C|C|O±€Ï…ÃP±€Ï…=btP˜ïŒº¥$¥$1-¤Ë€˜–€¤Ë€C#€0ÔŒa€Ï…Ï…ÛºÃPŒa€˜–€Œa€˜–€˜–€±€Ûºçï±€ô$ô$ Ž1-Œº¥$ŒºŒº€˜–€ 5C#€çïC|[æ$ø½5€çïYÏ…˜–€±Ã[æ$ø[ætPC|C|=b=b½5€ÃPÛº˜–€g€½5€±€€,€€,€g€g€C#€±€¤Ë€= $Ÿ[€ô$˜ïtPŒº=bO±Yô$¤Ë€½5€Œa€€,€7777ÔBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀh0 $’I$’I$’RI$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUUUUQTUUTUUUUUUUUð `[€[€Œa€Œa€€,€Œa€Usj±²| 5$Ÿ= Œa€I>¤Ë€¤Ë€I>0Ô±²}ú—‚7 ‚±²|$Ÿ€,€ÕŸ€Ûºç€g€s÷€$ŸI>= = $Ÿ+Ä~7 ‚7 ‚7 €…€Œas€Œa€Œasú—€jŒa€½5€˜–€Us$Ÿ$Ÿ$Ÿ0Ô 5+Ä|$Ÿjj€…‚7 €…€Œasú—€$Ÿg€Œa€[€= I>= = UsI>I>Us= $Ÿ±²}ú—ƒ+Ä~7 ‚7 €…‚7 ú—ú—‚±²|I>Ûº Žô$±€€,€s÷€0Ô[€˜–€¤Ë€Éj€¤Ë€Éj€ÕŸYÕŸ1-1-±€ô$UÌÃ$ø$ø[æ‚htƒV~ ŒºYY1-=btP€7777sBUFR&bÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÂUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½à„!B„!B„!BB„!B„!BÆ1ŒcÆ1ŒcÆ1ŒcB„!B„!B„!JP‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„µÏ„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUTTUUUUU@DUUUUUUð aŒºhhâ-Œº¥$€…=bçï½5€˜–€I>±€ÕŸYô$YÉj€Œa€çïÕŸ€[€= g€˜–€½5€Œa€[€Us[€€,€g€Éj€ÕŸ€˜–€Usj0Ôg€Us€,€¤Ë€Us0Ô+Ä~7 €$ŸUs¤Ë€˜–€I>= +Ä~7 ƒ+Ä~7 ‚7 ‚7 €$Ÿ¤Ë€½5€ÕŸ€Ûº€,€g€s÷€s÷€I> 5+Ä+Ä~±²+Ä}€…€Os€Œa€O‚±²| 5Us¤Ë€€,€= = jI>g€UsŒa€g€I>±²+Ä+Ä|+Ä|+Ä| 5˜– ŽÃ ŽÉj€˜–€g€s÷€I>I>˜–€¤Ë€0Ô= UsÉj€€,€˜–€s÷€g€±€Œa€7777ÿBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUTUUUUUUUð `ÕŸYI—€…¥$èHI>7 ‚±²~±²+Ä| 50Ô˜–$øÛºI—I>jUsUss÷€[€= Ø=bÛºg€[€[€s÷€s÷€±€¤Ë€½5[æÕøèH±YÃtPtPŒºh[æI—=bhI—˜ï1-Éj€½5€Éj€g€g€[€€,€±€¤Ë€s÷€¤Ë€¤Ë‚±²}€…ú—ƒ+Ä~±²~7 ‚7 ‚7 €…ú—€…€Œasú—€…€…€…ssú—ú—‚7 ƒ+Ä+Ä}ú—s€Œa€…ss‚7 €j€,€˜–€˜–€€,€€,€j= j$ŸUs¤Ë€€,€[€˜–tP€Œa€¤Ë€g€¤Ë€ÛºÉj€Œa€g Ž Ž1- ŽYÛº7777ŽBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð,0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUU@UUUUUAUUUUPUTUUUUUð `Ûºçïç€˜–€Œa€€,€˜–€s÷€Us$Ÿjj±²~±²~±²|= ˜–€˜–€¤Ë€Œa€s÷€˜–€g€Œa€s÷€= [€g€Éj€€,€¤Ë€$Ÿ+Ä}ú—ú—‚±²|Œa€Œa‚±²|˜–€ÕŸ€½5$øI—=b ŽÉj$øÉj€Éj[æÃÛº½5€Éj€±€½5€˜–€= $Ÿ+Ä~7 €s÷€ÛºÉj€±€s÷€[€€,€s÷€[€= = $ŸI>j$Ÿ±²|$Ÿjj7 ‚±²| 5I>I>[€I>I> 5+Ä|jUsUsUs[€Us˜–€˜–€Éj€ÛºÉj€˜–€çïô$Éj€ÕŸ€Éj€ÛºŒa€$Ÿ±²}€…€…ss€Osú—ƒ+Ä|$Ÿ7 ƒ+Ä|7777ŽBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUAUUUUPAUUUU@UUUUPUUUU@ð b±²}€…€Œasssú—€…€€,€Œa€½5€˜–€s÷€Uss÷€g€€,€g€= j= [€¤Ë[æ=b¤Ë€jj+Ä+Ä|$Ÿ˜– Ž1-ô$çï±€g€½5Y$øÉj€ÕŸ€ÕŸ€s÷€0Ô= I>$Ÿ±²}ú—€±²~7 €j€,ÃI—UÌ ŽŒa€±€g€g€g€Œa€˜–€s÷€[€0Ô€…s€…‚±²}ú—€O‚7 €jUsŒa€g€s÷€¤Ë€g€€,€I>[€Us˜–€˜–€€,€s÷€= j±²}ú—‚7 €…€…‚±²|j[€g€Us[€I>0Ôg€I>= s÷€= I>Œa€Us 5j+Ä}s‚7 €…‚±²}ú—ú—€7777ŽBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐX0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS c\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUU@UQ@UUUUUUUUPUUð ` 5= 0Ô= [€˜–€Œa€€,€g€Œa€±€€,€¤Ë€çïÃhY[æÃô$˜–€[€$Ÿ0Ô[€Œa€±€[€ 5+Ä+Ä~±²}€…‚7 ‚7 €j= I>g€g€0Ô 5+Ä|s€…s‚7 €7 €g€I>±²~±²| 5±²}€…‚7 €±²}ú—ƒ+Ä}ú—€…ƒ+Ä}ú—ú—€…‚7 € 50ÔI>Us[€[€UsŒa€±€[€€,€s÷€0Ô+Ä|j 5jj[€€,€¤Ë€¤Ë Ž1-ÕŸ€Œa€I>UsÉjÃô$€,€˜–€ 5±²}ú—‚±²+Ä|7 ú—‚7 €$Ÿg€˜–€˜–€[€0Ô$Ÿ$Ÿ0Ô[€7777ŽBUFR&bÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐUUUUUUUUUUU]kZÖµ­o{Þ÷½ï{Þ÷½ï{Þ÷½óœç9Îsœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{Þ€!B„!B„!BŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUUUUU@UU@UUU@ð `j0Ô= = 0Ô±²}ú—‚7 € 5j0Ô[€Œa€ÕŸ€çï€,€[€$Ÿ 5j0Ô[€˜–€¤Ë€¤Ë€¤Ë€s÷€[€$Ÿ$Ÿ±²}ú—€…€…‚7 ‚7 €jjjI>€,€€,€0Ô= j$Ÿ$Ÿ0Ô0Ô= Œa¥$±YtPh1-1-Ûº˜–€g€g€€,€Œa€¤Ë€€,€[€0Ô+Ä~7 s€…‚7 €j[€g€I>j 5j±²|I>g€= ú—ssss€…ú—ú—€…ú—ú—‚±²|= 0Ô 5ú—€…ú—€Œas€…€…€$Ÿs÷€= jjjj 5I>½5€½5€[€ 5+Ä}ú—‚7 €7777ÿBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUT@UUUPUUTTUQUUTPPð a€…s‚±²}ú—€…ú—€$ŸŒa€˜–€UsI>[€±€[€= g€I>Us0Ô+Ä|+Ä~±²}ú—€…ú—‚7 €…‚±²~±²| 5= g€[€[€UsUsI>= 5 50Ô 5+Ä+Ä~±²}s€…€Œas‚7 ‚±²|= s÷€UsUs0Ô$Ÿ0Ô0Ôj$Ÿ0Ôj+Ä|= 5 5±²~7 ‚7 ƒ+Ä+Ä+Ä~7 ƒ+Ä|0ÔUs$Ÿ$ŸUsj7 €jj$Ÿ0Ô= Us¤Ë€I>0Ôjú—ú—ú—ú—ú—ú—‚±²|jUs= ±²}€…ú—ú—‚7 ‚7 €+Ä+Ä+Ä~±²~7 €…ú—‚±²|€,€7777…BUFRöbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@ @"""""""""""333333333ˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™ª Št%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lu-sáN•µÀ …1Е-sáÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V׆٣díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUUUUUUUPUUUUUUUUUU@ð `±€¤Ë€½5€¤Ë€±€½5€ÉjÃÕŸ€g€0Ô0Ô[€g€g€= s÷€ 57 €…€…‚7 €I>±€Éj€ÛºÉj€±€±€Œa€€,€Œa€½5€¤Ë€I>$Ÿg ŽUÌ€,€s÷€[€= j 5Œa€½5€Éj€±€¤Ë€€,€˜–€[€[€Us0Ô$Ÿ$Ÿ= = 5±²~±²+Ä~7 €…‚7 ƒ+Ä|0Ô€,€I>$Ÿ$Ÿ$Ÿ+Ä+Ä|jjs÷€ô$Ûºô$ÕŸ€˜–€[€[€[€UsUss÷€Œa€˜–€Œa€Us$Ÿ$Ÿ 5ú—€…‚±²}ú—ú—‚7 € 50Ô[€= 5$Ÿ 5 5j= = Œa€½5€ô$½5€s÷€jú—ú—€…€7777BUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@H0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUUUUUUUUUTUUUUUUUPUð aú—€$ŸUs= 0Ôg€g€g€Usg€0Ô= I>0Ôjj 5+Ä}€…ú—‚7 ú—s‚±²+Ä|j= I>= = I>g€Uss÷€[€€,€Œa€Œa€€,€Ûº½5€½5€˜–€s÷€€,€I>jUs€,€˜–€¤Ë€s÷€g€Œa€[€[€UsŒa€s÷€I>Us0ÔÉj€Éj€= j7 ú—€$Ÿ$Ÿ±²+Ä|$Ÿ±²~±²~±²~±²|+Ä~7 €…€0ÔI>= 0ÔI>Us¤Ë€Us 57 €j 5 5Us½5€±€±€€,€€,€€,€¤Ë€±€½5€ÕŸ€ô$Éj€Us€,€½5$øÃs÷€[€I>0Ô±²}€…‚±²|s÷€¤Ë€ÛºÉj€€,€˜–€Œa€7777—BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@\0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠÇ>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUQUUUUUEUUUUU@UUTPð `€,€¤Ë€˜–€s÷€s÷€= Us¤Ë€€,€€,€Œa€˜–€½5€±€˜–€˜–€½5€Ûºô$˜–€€,€g€[€g€[€±€ÛºI—=b1-YÃçïÛºŒa€= [€±²|$ŸUsg€g€I>= 0Ô= $Ÿ 50Ô[€I>¤ËUÌ Žô$¤Ë€$Ÿ= +Ä| 5˜–€Ûºçï Ž¤Ë€½5€ÕŸ€ô$ Ž¤Ë€±€Œa€g€ÉjYÛº¤Ë€˜–€I> 5 5€…‚7 ‚±²}ú—€ 5+Ä~±²~7 ƒ+Ä|0Ô= 0Ô 5jÕŸ€çïçï½5€g€˜–€j+Ä+Ä~7 ú—ú—‚7 ú—ƒ+Ä}ú—€ 5±²~7 ‚7 €…€…‚±²}€…ú—€$Ÿs÷€7777—BUFR&bÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐBUUUUUUUUUUUUU]ï|ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷¾÷½ï{Þ÷½ï{Þ÷½ï{ÀB„!B„!B„"„ ‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUTUUUUUUD@UUUUTUUUUUTð aYUs7 ƒ+Ä~±²~7 ú—ú—‚±²}ú—ssú—‚7 ‚±²~±²}ú—ú—‚7 €ú—€0ÔŒa ŽÃI—ô$ÕŸ€±€[€Us˜–€ÕŸ€½5€s÷€Us 5j˜–€¤Ë€$Ÿ$Ÿ€…‚7 €…€0ÔÉj€[€˜–€½5€ÕŸ€UsUsg€¤Ë€½5€ô$=bYô$s÷€s÷€[€0ÔUsŒa€ô$ô$ÕŸ€Œa€I>I>±²|±²| 57 €…ú—€$Ÿ= I>I>$ŸI> 5= = 0Ôj$Ÿ 5 5jj$Ÿ0ÔŒaú—s€Œas€$Ÿ= $ŸI>0Ô0ÔI>Us= I>Us= [€I>UsUs= = 0Ôj0ÔI>j±²|7777ÿBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ 0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×Â2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUQ@UUUUAUUUUUUUUUUUQUUð `0Ô= 0ÔI>0Ô$Ÿj 5I>I>= = [€UsUsg€s÷€s÷ú—ú—‚±²}s€Œas€O€O€Osú—ú—€Œas‚7 ‚7 ƒ+Ä|0Ô$Ÿj 57 €+Ä+Ä~±²+Ä|0ÔUsg€€,€Œa€g€s÷€s÷€s÷€½5€Ûº1-UÌ1-Ys÷€g€= j±²+Ä| 5€,€çïÕŸ€½5€±€s÷€g€€,€Uss÷€s÷€I>$Ÿ 5j= I>I>= 0ÔI>UsI>s÷€Œa€€,€€,€Œa€$ŸUs˜–€s÷€[€g€¤Ë€ô$çï1-1-±€I>$Ÿj0Ô= ±²|= Œa€Éj€s÷€g€[€I>g€I>7777ÔBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ 0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUPUUUP@UQUUð `I>€,€Œa€ÕŸ€½5€Éj€ÕŸ±Y Ž[€˜–€±€[€0Ôg€¤Ë€Éj$ø Žçï½5€€,€ÕŸYô$½5€çïUÌY¤Ë€ÕŸ€Us[€$Ÿ= $Ÿ€,€[€½5€Œa€Œa€Us[€= [€[€0Ôg€s÷€g€[€j½5€¤Ë€Œa€±€Œa€= 57 €…ú—ú—‚7 €…sú—‚7 ú—ú—ú—ú—ú—‚7 ‚7 ‚7 ‚±²+Ä| 5I>I>s‚7 ú—ú—‚7 €I>[€0ÔjjI>= [€s÷€g€Us= = $Ÿ±²~7 € 5+Ä}€…€…ss€…‚±²|j= $Ÿj= j+Ä|jI>[€I>0Ôg€7777ÔBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ40 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUTEQUUUUUPTTUUQPUUUQPUUð `= $Ÿ±²|0Ôs÷€±€= [€Éj€Éj€Œa€g€UsUs 5±²+Ä|= j 5j+Ä|= I>$Ÿú—€$Ÿjj0Ôs÷€¤Ë€çïÛºg€s÷€[€Us¤Ë€g€˜–€¤Ë€g€Us= [€Œa€[€j±²+Ä~±²~7 ƒ+Ä}ú—€0Ô€,€= 7 €j$Ÿ 5±²|j$Ÿ 5= $Ÿ0Ô$Ÿ+Ä| 5$Ÿ 5+Ä~±²+Ä|jI>0Ô$Ÿjjj$Ÿ0ÔI>= = = $Ÿ[€€,€= +Ä|j+Ä| 5+Ä|j 5+Ä+Ä~±²}ú—‚7 ú—‚7 ƒ+Ä~±²~7 ƒ+Ä+Ä| 5j0Ô0ÔjUsj€,€7777ÔBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ЀL0 $’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%KkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUQUUUTUUUU@UUUUUUUUUUð `½5Y˜–€¤Ë€Œa€€,€Éj€g€I>I>s÷€Us0ÔI>€,€g€g€$Ÿ 5I> 5+Ä|0Ô0Ô= ˜–€€,€j[€s÷€±€½5€±€Œa€jjj+Ä~7 €…ú—ú—€…€…‚±²|$Ÿ0Ô0Ô$Ÿj 5 5 5j$ŸjUsg€I>[€[€I>7 ú—€…ú—s‚±²|= = 50Ô= I>I>j= [€0Ôg€I>+Ä|0Ô= 5$Ÿ[€s÷€0Ôg€Us€,€I>= 0Ô0Ôj$Ÿ+Ä|±²}ú—€…‚±²}€…€…€…ú—‚±²|0Ô= 0Ô= UsUsUsUsg€7777ÔBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ`0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ð‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUPUUUUUUUUUUD@TUQUPð `UsI> 50Ô= 0Ô0Ô0Ô0Ôs÷€[€0Ô 57 €…ú—ú—‚±²|jj 50Ô0Ô= $Ÿj0Ôj±²~7 ‚7 ƒ+Ä}€…ƒ+Ä|jUsI>¤Ë€½5€ÕŸ€ÕŸ€Ûº€,€Œa€Ûº½5€I>[€0Ô0Ô˜–€[€[€Us= ¤Ë€s÷€g€Œa€s÷€½5[æ˜ï[æ=bÛºô$[€ÕŸ€0Ôs÷€Us$Ÿj±²|$Ÿ+Ä~±²+Ä~7 ú—‚±²| 5= $Ÿ$Ÿ+Ä+Ä~7 ‚7 ‚7 ‚7 ƒ+Ä~±²~7 ú—‚7 € 5$Ÿ$Ÿ7 ‚7 € 5ú—€Œa€…‚7 ƒ+Ä| 5 5 5±²| 5 50Ô$Ÿ0Ô= +Ä~7 €7777ÔBUFR&bÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ЂUUUUUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï{Þ÷½ï{Є!B„!B„!BB„!B„!B„!ŒcÆ1ŒcÆ1ŒcÈB„!@Šˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUUTDUTUU@UPUð aú—‚7 ú—ú—‚7 ‚±²|jI>g€€,€[€= 0ÔI>0ÔI>= I>I>I>UsUs= 0Ô$Ÿ 5±²}ú—‚±²}ú—‚±²+Ä| 5 5$Ÿ= jI>[€g€Us$Ÿ$Ÿ= UsUs€,€¤Ë€= = 7 ‚7 ‚7 ‚±²| 5+Ä| 5j$Ÿj+Ä|±²|$ŸUsj$Ÿ 5+Ä~±²~±²}€…€…ú—‚7 €= €,€±€Us= UsI>[€0ÔI> 5±²~7 ƒ+Ä+Ä+Ä}ú—€…s€…s€Œasú—‚7 €I>= [€Us[€ 5j7 ‚±²~±²~7 €±²~7 ‚7 €±²~7 ‚7 €g€€,€g€s÷€7777ÿBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀ0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQAAUUU@UUUUUUPTUUUð `Us 5±²|±²+Ä| 5±²|j7 ú—ú—‚±²|±²+Ä|j= g€Us$Ÿ= = ˜–€Us0ÔI>[€j±²~±²~7 ú—‚7 €…ú—€…s€…‚7 €$ŸI>[€= g€Œa€€,€[€= ˜–€Ûº¤Ë€I>$Ÿ0ÔI>[€$Ÿ 5ú—‚7 ú—ú—‚±²|+Ä| 5 5$Ÿ 5+Ä|j+Ä}ú—‚±²~7 ƒ+Ä|= s÷€I>ú—‚7 s€Œas€…€…s€Œas€Œaú—ú—ú—€…‚±²| 5 5jI> 5+Ä~±²}€…ú—ú—ú—sú—‚7 €0ÔI>[€±€Ûº½5€€,€¤Ë€Éj€˜–€˜–€s÷€7777jBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀ(0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUPUUUUUUUUUUUUUUUTUUUUUUUUUUUð `Usj0Ô 57 ‚7 ú—‚±²|jI>s÷€Œa€s÷€[€€,€UsI>Us[€I>g€g€UsUsŒa€[€js÷€[€$Ÿ= €,€€,€Œa€¤Ë€s÷€Œa€g€Éj€˜–€[€Us0ÔUs= = = j= ±€±€s÷€g€I>$ŸUsUsUs€,€s÷€s÷€€,€[€= 0Ô$Ÿ$ŸI>I>0Ôjj+Ä+Ä|€…ú—‚7 ú—€…ú—€$ŸI>Us= 0Ôj= 0Ô= UsI>= 0Ô$Ÿ= UsUs0ÔjI> 5 5= 0Ô 5jj$Ÿ0Ô= $Ÿ$Ÿ= 0Ô$Ÿj$Ÿg€I>jjUs7777jBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀ@0’I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUUUUUUUUUUUUUUUUUUUUUUUð `0Ôj±²~7 €…€Œas€…€…‚7 €…ú—€…€…ú—€…‚7 ƒ+Ä|= = = $Ÿ$Ÿ= I>j0Ô[€€,€ÕŸ€±€½5€±€˜–€˜–€s÷€[€€,€Œa€s÷€I>s÷€s÷€Us[€Us0ÔI>jj$ŸŒa€Éj€ÛºYg€I>I>[€I>Usg€$Ÿ0ÔjI>I>€,€€,€= €,€g€g€= I>0Ô0ÔI>I>0Ô= = 0Ô[€UsUs= = ¤ËYô$çï¤Ë€¤Ë€±€½5€¤Ë€¤Ë€Éj€ÕŸ€UsUs$Ÿ= [€g€[€Uss÷€= 5$ŸŒa€€,€€,€= 0Ô$Ÿ0Ô±²|$Ÿ[€¤Ë€Ûºg€I>0Ô7777jBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀT0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðDUUUUUUUUUUUUUUUð aú—‚7 ‚±²}ú—‚7 ƒ+Ä~7 ú—‚±²~7 ‚7 ‚±²}ú—sú—s€…s€…s‚±²}ú—ƒ+Ä| 5 5+Ä|+Ä+Ä| 5+Ä~7 ú—‚7 €…€…s€…‚7 s€…s€…€…s€…ú—€…ú—ú—sú—€…ú—‚7 ‚7 ‚7 ‚±²}ú—ú—€…€…ú—ú—s€Œaƒ+Ä|$ŸI>I>Us[€[€= Us[€[€˜–€Œa€s÷€s÷€I>0Ô0Ô= 0Ô[€g€Us$Ÿg€Œa€s÷€˜–€±€g€€,€[€[€€,€±€±€Ûº±ÃÕŸ€¤Ë€Œa€Us˜–€g€g€˜–€¤Ë€ÕŸ€ô$Ûº½5€€,€ÕŸ€ô$¤Ë€€,€±€½5€s÷Y7777jBUFR&bÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÂ\ç9ε­kZÖµ­kZÖµ­kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½ï½ï{Þ÷½ï{Þ÷½ï{Þð‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUTUUUUUUUUDð `çïÕŸY$ø=b±€˜–€g€€,€±€±€Ûºô$$øYŒa€Œa€I>[€0ÔŒa€Œa€Éj€g€±€ÛºgÂYÛºÉj€ÛºÉj€Œa€¤Ë€Œa€¤Ë€±€g€= = I>Us0ÔUs½5€€,€ô$g€˜–€˜–€¤Ë€€,€s÷€s÷€Éj€g€jUsg€s÷€0Ôj 5 5 5 5jjj+Ä| 50Ô0Ôs÷€I>0Ôs÷€$Ÿ7 s€…€…€…ú—€7 ‚±²+Ä|[€js÷€ 5±²}ú—‚±²~±²+Ä|= Us= I>g€Œa€s÷€½5€s÷€= = Us[€UsI>I>[€Œa€[€$Ÿ7 €±²|7777ÿBUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠ2ÇJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUU@ð c+Ä| 5$Ÿ[€˜–€g€= j+Ä| 5j= 0ÔjŒa€¤Ë€= 5˜–€½5€[€j$ŸI>g€s÷€= = $ŸUs[€ 5 5$Ÿ0Ô 5g€ô$¤Ë€g€€,‚±²+Ä~7 ƒ+Ä~±²|$ŸjUsUs[€g€s÷€çï±€±€½5€Éj€çïÛº¤Ë€[€[€g€I>0Ôj 50Ô±€çï¤Ë€s÷€s÷€0Ô0ÔI>Us[€[€€,€UsUsj 57 € 5+Ä|j 5 5 5 5 5 5j$Ÿ$Ÿjj= 0Ô0Ô$Ÿ 5+Ä~7 ú—€…ú—€…s€…‚±²+Ä+Ä|7777€BUFRöbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@UUUUUVfffffffffffgwwwwwwwwwwwxˆˆˆˆˆˆˆˆˆˆˆ‰™™™™™™™ŠÆ¹ðŒ§JÚà†B˜èJ–ƹìkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„¹ðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUUUUUUUUUUUU@UUUTUUUUð c+Ä~7 €…€…ú—ú—€…ƒ+Ä| 5+Ä~7 ú—‚±²~7 ‚7 ‚7 €= = Us0Ô0Ôj0Ô0Ô0ÔUs= g€g€g€g€[€Œa€Éj€…1-Éj€¤Ë€= Ûº¤Ë€±€½5€ÕŸ€˜–€½5€Œa€[€[€[€I>I>Us= [€ 5$Ÿ= Œa€¤Ë€çï¤Ë€s÷€Us$Ÿ+Ä+Ä| 5 5j 5j$Ÿ$Ÿg€s÷€= j= 7 ‚±²}ú—€…€Œa€…sƒ+Ä|$ŸI>[€g€Usg€I>= 0Ô= = 0Ô 5 5$Ÿ0Ô= ±²|I>$Ÿj0Ô= UsI>0Ôj0ÔI>Usg€= €,€7777=BUFRæbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð<0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUUUUUUUPUUUUUUUUUUUUUAUPð `s÷€s÷€I>7 ú—€+Ä|7 €0Ô= I>UsI>I> 5 5I>$ŸUsI>= ¤Ë€±€g€I>$Ÿ7 ‚±²|$Ÿ 5[€[€I>0Ôj0Ô+Ä| 5j= Us0ÔI>ÕŸ€ÕŸ€½5€€,€s÷€ 5 5+Ä+Ä| 5= [€g€g€Usg€¤Ë€€,€Œa€0Ô= Éj€±€Éj€ÕŸ€±€s÷€Usj= g€$Ÿ 5= = [€˜–€= 0Ô 5 5$Ÿ$Ÿj$ŸUs 5jg€±€Œa€Œa€€,€½5€Ûº˜–€€,€s÷€[€g€s÷€$Ÿ+Ä~7 € 5+Ä}ú—ú—€…‚±²}ú—ƒ+Ä|$Ÿ= jUs+Ä}ú—€7777€BUFRöbÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐT@333334DDDDDDDDDDDEUUUUUUUUUUUVfffffffffffgwwwwwwpŠB˜èJ–ƹðŒ§JÚà†B˜èJšçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUPPUUUUUUPUUUUUð b±²|= = ˜–€s÷€$Ÿ€,€Œa€[€[€¤Ë€¤Ë€½5€Éj€€,€= 0Ô$Ÿ€,€jjUsj0Ô[€Œa€±€Ûº½5€s÷€= g€± ŽUÌô$I—¥$â-¥$€…[æ ŽÛº€,€g€çï Ž 5+Ä~±²}ú—‚7 ú—ú—ú—ú—‚7 ƒ+Ä~±²~±²~7 ƒ+Ä|7 ‚±²~±²~±²+Ä| 50Ԥˀô$Ûº˜–€s÷€ÛºŒa€±€çïÕŸ€±€çï¤Ë€˜–tPÃÛº$øÃÛº½5€[€$Ÿ˜–€Us+Ä~±²~7 ‚7 €= +Ä~7 ‚±²|j 5 5[€ô$YÕŸ€Éj€½5€˜–€Œa€I>[€Uss÷€s÷€j0Ôg€˜–€= 7777=BUFR&bÿ« fÐ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐUUUUUUUUUUUU]ï{Þ÷½ïœç9Îsœç9Îsœç9Î÷½ï{Þ÷½ï{Þ÷½ï{ß{Þ÷½ï{Þ÷½ï{Þ÷½à„!B„!B„!BŠçÂ2+k€" c¡,kŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUPPUUUUUUUUUUUUEUUUUð ` 5= 5g€s÷€¤Ë€±€¤Ë€s÷€€,€$Ÿ˜–€Œa€Œa€s÷€¤Ë€˜–€½5€çï¤Ë€˜–€˜–€Ûºçï$øÉj€Œa€Ûºs÷€ 5±²|j7 ú—€[€ÕŸ€½5€ÕŸ€Us+Ä+Ä~7 ú—‚7 ‚7 ‚±²~7 € 5I>j±²~±²+Ä|$Ÿ$Ÿg€I>¤Ë€Ûº Žô$ÕŸ€¤Ë€g€˜–€Éj€ÕŸ1-Éj€½5€˜–€[€ 5 5±€€,€j= $Ÿ= g€[€g€Us0Ô0Ô= Œa€€,€Œa€½5YÃÃ1- ŽÉj€¤Ë€€,€€,€I>j+Ä|= Usg€s÷€˜–€[€g€I> 5$Ÿs÷€s÷€$ŸI>UsI>= = 7777ÿBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@ 0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUUUUUPQUPUUUUUUUTð `$Ÿ0Ô 5 5= 7 ‚7 ‚±²~7 ú—€…s€…‚7 ‚7 €$Ÿs÷€Éj€Éj€Éj€½5€˜–€Œa€g€[€= Us€,tPI—Éj€¤Ë€Œa€˜–€[€g€UsŒa€ÉjhÉñYŒºtPI—YçïŒa€€,€˜–€Éj€çïçï½5€½5€Éj€±€Éj€çïÕŸ€¤Ë Žô$ ŽçïÕŸ€€,ƒ+Ä+Ä|jj+Ä|$Ÿg€Œa€[€0Ô+Ä+Ä~±²+Ä~±²|jjjI>0ÔI>g€I>$Ÿ$Ÿ¤Ë€˜–€˜–€s÷€€,€Œa€çïÉj€±€˜–€˜–€¤Ë€±€Us0Ôs÷€Œa€˜–€0ÔI>Us0Ôú—ú—€ 5 5+Ä+Ä|I>g€€,€7777Ä|BUFRæbÿ« fÐ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@ 0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’[m¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž…-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUETUUUUUPUUUPUUUð `g€UsUsUsI>Us½5€½5€Éj€½5€Éj€±€½5€ÕŸ€çï½5€±€Éj€½5€½5€±€±€±€Éj€½5€€,€g€Us[€0Ô$ŸUs€,€Us±$ø[æI—ô$˜–€Usj 5 5 5 5 5±²~±²~±²|0Ô$Ÿ= $Ÿ$Ÿ+Ä|$Ÿ€,€[€j 5+Ä~±²| 5 5Uss÷€g€g€Uss÷€s÷€UsUs€,€ŒaY±€Éj[æ€Éj€½5€½5€˜–€¤Ë€jj€…s€…ƒ+Ä|€,€˜–€g€0Ô$Ÿ 50ÔUsI>Us0ÔUs0Ô[€0Ô$Ÿ+Ä~±²~±²~±²+Ä|$Ÿ= [€˜–€˜–€UsjjUs0Ôg€±€Ûº7777Ä|BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@40I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUU@UUUUUUUUUUUPUUUUð `Éj€ô$ÃYYYÕŸ€€,€s÷€I>jUs€,€±€ÕŸ€¤Ë€½5€½5€Éj€±€±€½5€ÕŸ€ÛºçïÕŸ€ÕŸ€±€Éj€˜–€˜–€Éj€j7 €…ú—€jg€½5€Éj€ÕŸ€½5€Éj€½5€Éj€Œa€Éj€ÕŸ€½5€Œa€s÷€j+Ä+Ä}ú—€…ƒ+Ä~7 €…€…ú—ƒ+Ä| 5 5 5j$Ÿ 5 5$Ÿj0Ôjj0Ô0ÔI>$Ÿg€0Ô 5$ŸI>0Ôg€I>+Ä~7 ƒ+Ä~±²+Ä|= [€±€g€ۺۺs÷€[€[ú—s€…s€Œa€Œa‚7 €= €,€g€Œa€½5€ÕŸ€s÷€s÷€Éj€Ûº˜–€s÷€˜–€[€Œa€= = [€€,€7777Ä|BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@L0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUEUUUUUUUUUUPUUUUUUAð `0Ô 50Ô[€g€s÷€€,€Œa€s÷€€,€g€€,€¤Ë€ÕŸ€çïYçï½5€ 5j+Ä~±²|I>+Ä|j+Ä| 5g€½5€€,€[€g€= [€0Ô€,€g€˜–€±€ÕŸhUÌý5€Éj€½5€˜–€[€I>= = g€€,€g€Us0Ô= 0ÔI>I>$ŸUss÷€= UsUsI>I>j7 ƒ+Ä+Ä}ú—sú—ƒ+Ä|Œa€˜–€g€UsUsUsI>= [€€,€ÕŸ=b[æ1-Ûº±€s÷€Œa€€,€g€Us0Ô0Ô$ŸI>I>= $Ÿ±²~±²| 5±²}ú—ú—ú—ú—‚7 ú—‚7 ‚±²~7 ú—€…€…ú—ú—€…€…€…ú—‚7 €7777Ä|BUFRæbÿ« fÐ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð@`0I$’I$’I$¤’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN•µÀ …1Ð¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUPUUU@UUUU@UUUð `0Ô0Ôs÷€g€±€±€¤Ë€ô$ô$Éj€s÷€˜–€¤Ë€½5€€,€ 5j= ˜–€ÕŸ€Éj€±€½5€¤Ë€Œa€±€Éj€çïÕŸ€Œa€UsI>j±²}ú—s‚7 ‚7 €…‚7 €j= €,€Œa€ÕŸ€s÷€[€I>g€s÷€[€˜–€Œa€˜–€¤Ë€˜–€˜–€Œa€ 5O€…€O€Œa‚7 ƒ+Ä|UsŒa€[€Us[€0ÔI>I>I>I>0Ô 5+Ä~±²~7 ‚±²}€…€O€ 5+Ä+Ä|0ÔŒa€ÕŸ€±€˜–€¤Ë€±€[€[€[€Œa€¤Ë€ÛºÛº¤Ë€j 5+Ä+Ä+Ä|g€j±²+Ä+Ä|I>s÷€$Ÿ= 0Ô0ÔI>jj= g€j7777Ä|BUFR&bÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐBUUUUUUUUUUUUUUUUUUUUUUUU^sœç;Þ÷½ï{Þ÷½ï{Þ÷½ï@„!B„!B„!D!B„!B„!B†1ŒcÆ1ŒcÆ1ŒcÈ@‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUTUUUUUUUUUU@UUUUUð `j[€$Ÿ$Ÿ0Ô0Ô 5+Ä+Ä|$Ÿ[€g€[€0ÔI>s÷€g€= g€Us˜–€Éj€çï±€Œa=bÃÛºÉj€˜–€Œa€Œa€[€0Ô[€€,€€,€€,€g€s÷€g€I>= = g€0Ô[€Us$Ÿ= ú—ú—‚7 ú—‚7 ú—‚±²|jUs˜–€±€g€= 0Ô$Ÿ0Ôj0Ô= UsI>s÷€½5€˜–€ô$ÛºÕŸ€[€j 5j0Ô= s÷€Œa€˜–€Œa€s÷€€,€g€[€[€UsUsI>j$Ÿ 5 5±²}sú—s€…s‚±²|[€˜–€¤Ë€[€[€Us= I>[€½5Yçï ŽYô$½5€½5€g€$Ÿ 57777ÿBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUU@UUUUUUUUUUAUð b±²}€…ú—€j0Ԥˀ€,€Us= = ˜–€g€g€s÷€Œa€¤Ë€±€€,€s÷€[€s÷€= j0Ôj$ŸUs€,€˜–€˜–€€,€Œa€€,€s÷€g€€,€¤Ë€Éj€Ûº½5€½5€Éj€½5€çïçïYÉj€½5€g€0Ô= s÷€˜–€¤Ë€˜–€˜–€s÷€s÷€Œa€s÷€Œa€˜–€±€˜–€¤Ë€˜–€˜–€€,€˜–€Us 5ú—‚7 ‚7 €$ŸI>j= 0Ô$Ÿ+Ä| 50Ô[€€,€UsŒa€€,€Éj€¤Ë€¤Ë€€,€0Ô= UsŒa€ÕŸ€Éj€g€g€[€[€g€Us0Ô[€Ûºô$ÛºÛº±€€,€˜–€½5€s÷€= 5+Ä+Ä|0ÔŒa€ÕŸ€Œa€I>7777–€BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ(0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUUUUUUUUUUUUUUUUUUUUUUUð `j 5 5$Ÿ¤Ë$øÉj€[€$Ÿ$ŸUs0Ôjú—€…‚7 €$ŸŒa€±€½5€Éj€Éj€s÷€I>s÷€s÷€ÕŸY Ž ŽçïçïçïÛº€,€g€€,€I>UsI>Us±€¤Ë€¤Ë€±€±€˜–€½5€½5€ÕŸ€ÕŸÃh€ô$ÕŸ$ø$øÃçïÕŸ€½5€Œa€€,€€,€Œa€½5€½5€½5€½5€±€±€±€½5€Ûº½5€ÛºÃ Ž ŽI—1-Ã Ž¤Ë€±€s÷€= 0Ôg€Œa€€,€˜–€¤Ë€Œa€˜–€s÷€€,€g€€,€¤Ë€±€€,€˜–€Œa€= s÷€0Ô+Ä+Ä~±²~±²}€…€…€$Ÿ+Ä| 5 5$Ÿ= I>= ˜–€¤Ë€= ˜–€ô$ÕŸ€7777–€BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐ<0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUPUUUUTUUUUUUUUUUUUUUUUUð `½5€çï½5€½5€ÕŸ€±€Œa€€,€€,€Œa€¤Ë€˜–€˜–€s÷€¤Ë€ÛºÉj€½5€€,€¤Ë€˜–€€,€0Ô$Ÿ$Ÿj+Ä+Ä+Ä|I>I>Us˜–€çï=bô$½5€ÕŸ€€,€Uss÷€˜–€ÕŸ€ô$Éj€g€0Ôjssú—€…ú—ú—€ 5˜–€Ûº½5€Éj€±€g€[€¤Ë€±€ô$Ã$øYçïçïÉj€½5€±€˜–€˜–€g€g€˜–€¤Ë€Éj ŽÕŸ€s÷€¤Ë€s÷€[€I>€,€ô$$ø$øI—Ãçï±€s÷€g€UsŒa€¤Ë€ÛºÛºÉj€ÕŸ€¤Ë€Œa€Œa€€,€s÷€s÷€Œa€Éj€ÛºçïY ŽYçï½5€¤Ë€±€Œa€¤Ë€UsUs7777–€BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ЀT0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹò+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUTUUUTUUU@UUUUUUUð `I>[€Œa€½5€ÛºÛº½5€ÕŸ€Ûº½5€½5€½5€çïY ŽYô$Éj€½5€±€¤Ë€¤Ë€˜–€UsUs= [€s÷€€,€s÷€[€€,€€,€g€s÷€s÷€˜–€Œa€Œa€Œa€g€[€j±²}€…€ú—€Œa€…€Œa€Ûº¤Ë€s÷€g€€,€= I>0Ôg€±€˜–€[€Œa€g€j€…s€…s€Œa€…€= ÕŸ€Ûº€,€I>s÷€s÷€Œa€¤Ë€±€çï±€[€0Ôj 5ú—€…‚7 s€Œa€…‚7 €$ŸUs= 0Ôj 5$Ÿ= I>g€€,€¤Ë€ÕŸ=bÛºg€s÷€$Ÿ= 0Ôú—‚7 €= ÕŸ$ø=bçï±€g€0Ôj$Ÿ7777–€BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ѐh0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUTPUUTQUUUPUQUUð `$ŸI>Œa€ÛºI—=bçïÉj€¤Ë€g€$Ÿj+Ä~±²|$Ÿ€,€¤Ë€Œa€g€s÷€˜–€s÷€˜–€˜–€±€ô$ÛºÕŸI—1-Y ޽5€˜–€˜–€¤Ë€[€I>0ÔI>Us= j[€$Ÿ$Ÿ$Ÿjj0Ô= [€0Ô+Ä|I>ú—‚±²}ú—€…ss€ 5= j$Ÿ 5$ŸI>[€[€$Ÿ+Ä~±²|jI>¤Ë€= ú—€ 57 €…€Œa€Œa‚7 ‚7 € 5jj$Ÿ0Ôs÷€g€Éj€g€= 5 5$Ÿ$Ÿ 5Œa€…€Œasú—‚±²|I>g€s÷€s÷€$Ÿ 5+Ä| 5= Œa€ÕŸ€ÕŸ€Éj€±€¤Ë€7777–€BUFR&bÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ЂUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_x!B„!B„!B„B„!B„!B„!cÆ1ŒcÆ1ŒcÆ1Œ„!B„!B„!B¥)JP‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUUUUUU@UUUUUUUUUUUUP@ð `Œa€j±²}ú—€…€Œa€…‚7 €Us˜–€Œa€s÷€= 0Ô$ŸI>= [€€,€ÕŸÃçïŒa€€,€¤Ë€˜–€Usj+Ä+Ä}€…‚±²|0Ԥˀ˜–€Œa€s÷€0Ô= ½5€¤Ë€ÛºçïÕŸ€˜–€g€= I>0Ô+Ä}ú—€…ú—‚7 €jŒa€Éj€ÛºÛºçï±€g€I>I>Uss÷€Éj€ÕŸ1-1-1-Ûºç€¤Ë€±€I>$Ÿ0Ô[€€,€±€½5€¤Ë€g€= $Ÿ$Ÿ0Ô= ±$ø=bUÌI—1-Ûº±€g€Œa€¤Ë€g€j 5 5+Ä+Ä+Ä| 5= $Ÿ±²~7 ‚±²~7 €…ss€Œa€Œa€O€…€Œa€Œas€…€7777ÿBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀ0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠc¡*kŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUTUUUU@UUUTUUUUUUð `$Ÿ¤Ë€Éj€s÷€I>[€Uss÷€±€ÕŸ€˜–€s÷€= 5 5ú—€…€…‚7 ‚±²|$Ÿs÷€Éj€Éj€±€Éj€Ûºô$$ø$ø ŽYÛºÉj€˜–€$Ÿ+Ä}ú—‚±²}€…€…€…ú—€$ŸŒa€¤Ë€¤Ë€€,€€,€€,€Œa€˜–€±€ÛºÛºçï½5€˜–€€,€[€$Ÿ±²~7 €…€…€= s÷€¤Ë€Œa€Œa€Œa€€,€s÷€€,€Œa€¤Ë€±€Éj€¤Ë€Ûº0Ô+Ä~7 ‚7 ‚7 ‚7 ú—‚±²|Œa€ÕŸYçïçï¤Ë€±€Éj€çï=bI—çï½5€˜–€[€Us[€Us±²+Ä}ú—sss€jUs€,€€,€[€s÷€Œa€±€±€½5€77775BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀ,0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ð‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@UUUUTUUUUUUUUUUUUUUUUU@UUUUð `ÕŸ€ô$˜–€s÷€[€Us0Ô0Ôj+Ä~7 ‚7 €…€Œa€j€,€s÷€= j= j0ÔI>g€Éj€ÕŸ€¤Ë€Éj€±€€,€½5€˜–€ 5 5+Ä|j˜–€ÕŸ€ô$Éj€±€Œa€g€[€€,€Ûº=bhI—1-I—I—=bYçïÛº±€Œa€¤Ë€¤Ë€½51-UÌ=b=bÕŸ€ÛºÉj€çï$ø[ætPèH²™H±Y½Ž‚ ç²½Ž ޱ€¤Ë€½5€Éj€ô$ ŽYÛºô$ÕŸ€ÛºÛº±€Éj€Ûº±€¤Ë€¤Ë€s÷€[€$Ÿ 5±²}ú—€…‚±²|jUsô$1-çïŒa€¤Ë€€,€s÷€Œa€¤Ë€ÛºUÌâ-±YUÌ=b1-Ûº77775BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀD0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUPEUUUUUUUUUUUUUPUð `Œa€= s÷€[€[€Œa€çïhI—I—ÕŸ€˜–€g€Us±€Éj€±€±€¤Ë€g€0ÔI>Éj€ÛºçïÃÛº±€˜–€$Ÿ€,€ÛºÉj€ÛºÕŸ€½5€¤Ë€±€ÕŸ€çï½5€€,€[€I>I>$Ÿ$Ÿj±²}ú—s€…sú—‚7 € 5j+Ä+Ä|+Ä| 5I>€,€½5€½5€Œa€Œa€Us0Ô0Ô0Ô˜–€€,€= $ŸUs±Ã ŽÃ ŽçïÕŸYÉj€Éj€ÛºÉj€Éj€Éj€±€±€¤Ë€±€˜–€€,€€,€Œa€±€½5€½5€¤Ë€s÷€[€[€s÷€˜–€±€Éj€Éj€ÕŸ€±€I>[€ú—€…€O€Œa€…€…€0ÔUs€,€77775BUFRæbÿ« fÐ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÀX0’I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUUUUUUUUUUUUUUT@UU@UUUð `s÷€g€g€g€g€g€ÉjY$øYÃô$½5€€,€0Ô+Ä+Ä+Ä+Ä| 5s÷€½5€çïô$ÕŸ€ÕŸ€ÕŸ€ô$à Ž$øtP$øô$Yô$˜–€UsI>I>Œa€s÷€g€Éj€çïô$$øYô$çïçïçïçïô$çïÕŸ€˜–€[€s÷€[€Us 5jj0ÔUs$ŸUsg€I>I>$Ÿj½5$øô$¤Ë€= $Ÿ$Ÿj+Ä~7 ‚±²~7 ‚7 €…sú—€ú—€…ú—ƒ+Ä+Ä+Ä| 5Éj€¤Ë€€,€ÕŸ€Œa€ÕŸ€¤Ë€[ƒ+Ä~±²~±²~7 € 50ÔÕŸ Ž Žô$çïÛºô$çïçïÉj€±€Œa€€,€77775BUFR&bÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐÂUUUUUUUUUUUU]kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½èB„!B„!B„!„ ‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUEUUUUUUUUUUUUUUPUUUUUð `€,€g€[€UsjUs 57 €…€…‚7 € 50Ôg€s÷€s÷€g€UsUsg€s÷€€,€Œa€s÷€g€s÷€s÷€Usj+Ä| 5+Ä| 5 5I>Uss÷€€,€€,€s÷€[€Œa€˜–€±€½5€˜–€s÷€Œa€Œa€¤Ë€Œa€g€$Ÿ0Ô= j= Us0Ô[€Éj€½5€€,€g€€,€Uss÷€Uss÷€€,€UsUsI>0Ô 57 €…ú—s€…€…‚7 € 50ÔUsg€UsI>s÷€g€˜–€ÕŸ€ô$ô$ÛºÕŸ€g€¤Ë€Œa€g€$Ÿ±²~±²~7 ‚7 ú—€$Ÿ= = Usg€€,€½5€±€¤Ë€çïY$øY½5€Éj€çïçïÕŸ€˜–€[€I>7777ÿBUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð 0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUU@UUUU@UUUUUUUUUUTUð `I>j 5Us˜–€€,€[€UsUsg€Œa€s÷€Usg€Us0Ôj+Ä~±²~7 €…‚7 €…ú—s€Œasú—€ 5= g€¤Ë€¤Ë€s÷€Œa€¤Ë€¤Ë€ÕŸ€ô$±€Œa€g€[€= j±²}ú—‚7 €…€…€…€0Ô[€g€[€g€s÷€g€Œa€¤Ë€˜–€s÷€g€€,€Œa€Us$Ÿ 5+Ä~±²~7 ú—€…‚7 €I>Œa€ÕŸ€Éj€ÕŸ€ÕŸ€ÕŸ€½5€ÕŸYÃÛºÕŸ€±€ÕŸ€Œa€Œa€€,€= jj$Ÿg€՟YçïÕŸ€˜–€±€Éj€Éj€ÕŸ€½5€˜–€˜–€±€Éj€˜–€[€0Ô 5 5€…s‚±²|I>= UsUsI>= 7777 BUFRæbÿ« fÐ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð 0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUUUUUUUUUUUUUUUTUUUð `g€g€€,€±€±€ÕŸ€ô$Ûºô$½5€±€€,€jj±²~7 ‚7 ‚7 €= ˜–€˜–€Œa€s÷€g€I>[€[€Œa€˜–€Œa€¤Ë€€,€s÷€€,€[€ 5+Ä~±²|Œa€Œa€Œa€…‚7 €I>€,€€,€Œa€€,€= Us$Ÿ0Ô 5Us0Ôs÷€±€˜–€[€$Ÿ7 ú—€Œas€…ú—€jI>¤Ë€½5€±€çï Ž¤Ë€ô$ô$=bYÉj€˜–€¤Ë€Œa€€,€= ±²~7 sú—‚7 €[€˜–€ô$çïÉj€ÕŸ€ÕŸ€½5€€,€¤Ë€Œa€g€= 0Ô0Ôj7 ss€Œa€Œa€Œa€…€j€,€Éj€ô$¤Ë€€,€Ûº€,€g€€,€I>I>0Ô= 7777 BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð40$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUPýà`€,€I>$Ÿú>îbîbîb‚+k€ 5½5$øÃYY¤Ë€Ï…½5€±€½5€çïO±O±€€,€€,€€,€I>g€ 5j$Ÿs÷€˜–€½5Y1-=bÃYÛºÛºçïYÃÃYÏ…çïçïçïÛº±€¤Ë€Éj€±€Ï…ÛºÛº$øÃÃ=b Ž1-=bI—I—O±I—ô$ Žô$ô$ô$YçïçïۺυÉj€½5€½5€Ï…ÃÛº½5˜ïtP1-˜–€˜–€Œa€€,€˜–€Œa€€,€¤Ë€¤Ë€±€±€Éj€½5€½5€±€±€½5€½5€Ï…$ø$øÏ…ÛºÛº±€ÛºÉj€Éj€¤Ë€±€½5€˜–€˜–€€,€€,€$Ÿ¥}~¥}|7777 BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐL0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠB˜è[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUPð b±²|0ÔŒa€Éj€˜–€¤Ë€¤Ë€˜–€¤Ë€½5€¤Ë€˜–€Œa€Œa€˜–€Œa€s÷€[€½5€¤Ë€˜–€[€j$Ÿg€[€[€[€s÷€€,€˜–€±€Éj€ÕŸ€Éj€ÕŸ€ÕŸ€Éj€Éj€½5€±€±€±€¤Ë€€,€g€I>I>s÷€g€g€[€g€€,€s÷€€,€€,€Œa€s÷€€,€€,€€,€±€˜–€½5€±€Éj€¤Ë€±€½5€±€±€Éj€ÕŸ€½5€½5€±€½5€±€ÕŸ€ÛºçïÛºÛºÛºÉj€½5€˜–€s÷€s÷€I>0Ôj 5j[€€,€[€[€UsUsg€[€g€s÷€g€s÷€g€I>g€˜–€˜–€±€ÕŸ€Ûº˜–€[ƒ+Ä~7 ú—ss€…ú—‚7 €$Ÿ[€7777 BUFRæbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ð`0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUA@UUUUUUUUUUUUUUUUUUUUUð `I>0Ô$Ÿ$Ÿ±²+Ä|±²}ú—s€O€O€Œa€O€Œa€…€…ss€…s€Œas€Œaú—€7 ‚7 €…ú—€…€…€…‚±²}€…€Œa€…ú—ú—‚±²|$Ÿ 5 5 5Us[€Us$Ÿg€Éj€ÕŸ€˜–€˜–€˜–€g€$Ÿ$Ÿs÷€UsI>s÷€±€Éj€çïô$çïô$Y$øUÌUÌ=bÃ1-[æ[æI—1-çïs÷€I>g€UsI>I>€,€½5€[€[€€,€ÕŸ€çïçïÃtP½Ž¥$¥$˜ï[æ$ø=b Ž Žô$Ûº½5€ÕŸ€çïÛºÕŸ€±€½5€˜–€±€ÕŸ Ž1-1-1-1-$ø1-$ø7777 BUFRfbÿ« fÐ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÐUUUUUUUUUUUUUUUUUUTD»»»»»»»»»»»»»»»»»»»»»»»»»^s½ï{Þ÷½ï{Þ÷½ï{Þ÷Þ÷½ï{Þ÷½ï{Þ÷½ïx!B„!B„!BB„!B„!B„!ŒcÆ0‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k„C!Lt%Kc\øFS¥mpC!Lt%lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUPUUUUUPEð a1-à Žô$Éj€Éj€Éj€±€˜–€Éj€Éj€ÛºÕŸ€çïçïYY$ø=bh[æ[æ[怅ŒºI—$ø ޽5€±€¤Ë€g€g€[€= $Ÿ$Ÿ= I>0Ô+Ä~±²~±²}€…ss€…s€Œas‚±²~7 ‚±²~7 ‚7 €= $ŸI>s÷€¤Ë€a¨s÷€a¨Us= 0Ô= 5±²+Ä~±²}ú—€…sú—‚±²}€…s‚7 €…€= a¨I>I>Us€,€˜–€Œa€ô$çïáÔ€½5€a¨€…€…sú—‚7 €…€I>a¨ÉjYÃáÔ€áÔ€Éj€½5€ÕŸ€áÔ€¤Ë€s÷€= I>a¨= = g€= j+Ä+Ä|+Ä|0ÔÉj€7777BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUEUUUUUUUUUð aYtP=b1-1-$øçïÉj€çïY=btPn6bn6I—ÃçïŒa€= 0Ô= ˜–€Éj€Éj€ÕŸ€áÔà ŽÃ=b=b Ž=b$øô$ô$YáÔ€áÔ€áÔYYYô$¤Ë€˜–€Éj€Éj€½5€½5€˜–€Œa€€,€€,€¤ËYô$áÔ€çï½5€€,€çï€,€I>a¨= 5+Ä|0Ôs÷€s÷€s÷€Œa€0Ôj$Ÿj$Ÿ±€Éj€½5€Œa€s÷€s÷€Œa€s÷€0Ô+Ä|0Ôg€áÔY=b Ž1-½5€±€¤Ë€s÷€½5 ŽY$ø1-1-$øYÃ=b=bÃYô$YYÃtP¥$‚ô}ô}bZÕø€7777ô$BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@$0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ð‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUPTU@UUUUUUUUUUUUUð a˜ï±YŒº=b$ø$øô$áÔ€½5€±€g€s÷€j= s÷€Uss÷€Œa€s÷€a¨I>= g€g€s÷€¤Ë€Œa€g€I>j±²~7 €…‚±²}€…€…€O€Œa‚±²|js÷€= j±²+Ä+Ä+Ä~±²|j$Ÿj 5±²}ú—sú—€…€Œaú—ssƒ+Ä|0Ôg€˜–€a¨j 50ÔUsÉj€çïçï±€¤Ë€a¨0Ô 5±²| 5+Ä}€…ƒ+Ä|¤Ë€áÔ€ô$½5€áÔ€±€€,€g€g€¤Ë€ÕŸ€ô$çï±€s÷€I>g€j±²| 5 5ja¨áÔ€áÔ€±€Œa€s÷€0Ô= g€€,€˜–€½5€½5€ÕŸ€áÔ€s÷€Œa€$Ÿ7777ô$BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@<0I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐŠ …1Е-sáN•µÀ …1Е1®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUýàb+k€ú>tP€ú>tP€I>Uss÷€[€I>Us= s÷€˜–€¤Ë€Éj€½5€Éj€çïô$ÛºÛºÛºÉj€Éj€Éj€±€½5€½5 Ž1-$øô$ ŽY ŽYô$à ŽYô$YÛºçïÕŸ€Éj€Éj€½5€Éj€ÕŸ€çï Žh˜ïÉØï˜ïtP$ø1-1-hUÌÃ$øI—1-=b$øÃ ŽÃ ŽYçï$øUÌUÌhtPUÌŒº€…tP€…â-˜ï‚² ç=»½Ž˜ï€…˜ïhUÌI— Ž=bb˜ïhI— Žçïô$1-UÌhI—=bÃ$ø=bÃ1- Ž$øYÛºÉj€ÕŸ€Ûºô$çïçï7777ô$BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@P0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUPUUUUUUUUýà`ô$ÕŸ€ÕŸ€ÕŸ€ÛºÛºô$1-=bô$ÕŸ€ÕŸ€Ûºçïçïô$ÕŸ€ÛºÕŸ€ÛºÕŸ€Éj€Éj€±€s÷€[€[€s÷€Œa€s÷€Œa€±€±€¤Ë€±€±€€,€€,€[€I>$Ÿjj$Ÿ[€[€s÷€¤Ë€½5€Ûº Ž$ø1-Éj€Éj€˜–€s÷€¤Ë€€,€€,€˜–€g€0ÔUs= 5= ¤Ë€ô$Y±€˜–€g€I>Us[€g€¤Ë€¤Ë€[€0ÔI>g€I>jîbƒ}tP€ú>€ú>‚+k€ 5s÷€½5€Éj€€,€€,€UsUsŒa€±Y Žô$±€¤Ë€¤Ë€½5€s÷€I>$Ÿ~¥}|$Ÿ¤ËÃ=b=bô$±€s÷€Œa€½5€¤ËÃÃ7777ô$BUFR¶bÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@d0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$–Ûm¶Ûm¶Ûm»`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ ^1†Ä鬯~ðO€O€j0ÔÃP øP,@ †GÏ…1-²&\ L¸ýàI>¤Ë$øIðÄ´ 'ÀÐ$Ÿ9ûÀ^šÀ= 0Ôa¨ÃP q°&% ReÀ[€·ô$$ø† ¡ 5@AI—u n ß4™p-pUs¤Ë=bd¡ –¨¦°3á@†GUÌ·Í nˆÈÐ#`s÷ ŽbZÄ´dp @@mݤˀzÃPÃP ‰h @@˜– ŽÏÞŸ¼?x ÓXýàOX€º(A˜ïƒJIc¾ ß4\À'¬@F0À†Gçïb%ª|(~ð!‘À= dµ@ÉjI—“.KT –¨ýà@@s÷€Ï…Ÿ >é¬ –¨™p)2àX€@¤Ë€7777$BUFR&bÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑBUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷½ï{ÞðB„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œc!B„!@Š2ÇBT¶5Ï„e:V×D2ÇB–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUU@UUUUUUUð `ÕŸ€ÕŸ€Éj€áÔYYÕŸ€±€±€˜–€˜–€¤Ë€ÕŸ€áÔ ŽYô$Y ޽5€áÔ€Éj€ÕŸ€½5€±€Œa€s÷€s÷€˜–€˜–€áÔ€Éj€ÕŸ€±€Éj€çï$øÃY ޱ€˜–€¤Ë€a¨I>Us= jUs½5€ÕŸ€Éj€Éj€ÕŸ€ô$çïÕŸ€½5Y$ø1-=b$ø$ø=bn61-¤Ë€Œa€Œa€Us= I>I>I>s÷€Œa€€,€I>0Ô0Ô0Ô 5$Ÿa¨s÷€€,€I>I>ja¨a¨€,€UsI> 5+Ä}€…‚7 €j0Ô= I>= I>g€a¨g€՟€˜–€áÔU̱€a¨€,€g€I>I>s÷€¤Ë ŽUÌ Žô$ô$77775€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTUUUUUUUUTUUUUUUUUUUUUUUU aYÛºçï¤Ë€Éj€ô$ô$ ŽÉj€Ï…jZZ~6â-€î hâ-€0Ô€,€˜–€€,€s÷€OX€0Ô[€I>½5€½5€±€s÷€g€I>OX€OX€ 5h€î €s÷€î €î h€ 5˜–€Éj€˜–€0Ôg€OX€[€˜–€±=bUÌUÌ[æ ŽÛºÏ…çïô$$Ÿâ-â-h€g€˜–€±€˜–€Œa€g€[€g€Œa€Ï…YYYô$ô$YÏ…½5€¤Ë€g€g€g€Œa€Ï…UÌ¥$¥$hI—Ï…s÷€Éj€±$øh=bÃô$ô$YçïÛº Žçïçïô$Ï…¤Ë€s÷€€,€0ÔI>= 0Ôj$Ÿ0ÔI>OX€I>I>7777¨BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€(0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJšçÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUð `UsI>0Ô 5€…€…s€Œa€O€Osú—‚7 ƒ+Ä|+Ä+Ä|+Ä+Ä~±²~7 ƒ+Ä}ú—ƒ+Ä}€…€Œa€…ss€…ƒ+Ä|= áÔ€ô$ÕŸ€çï Žçï ŽYÉj€ÕŸ$øçï±€˜–ÃUÌ=b1- ŽÃYáÔ€ÕŸ€áÔ€…îbÕø€…$øb€…btP¥$€…˜ï‚ çô}Õøâ-ô}Œº$øÃYçïçïáÔÕø‚%QÊ‚%Qçïa¨ÕŸ€ô$=bn6UÌI—I—b1-I—UÌbb Žô$=b¥$‚%QIðV%€…UÌUÌ€…n6I—tPâ-±YŒº˜ïI—UÌI—1-$øô$±€±€7777¨BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶ÛrI$’I$¶Ûm¶Ûm¶ÛmÛ`Šc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡/„e:V×D6¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUPUUUUP `±€ô$ ŽÏ…çïçïÏ…ô$çï½5€Ûº=bUÌ€…€…€…1-Yô$YÛº½5€±€Ï…Éj€Ûºô$ÉjYYÉj€Éj€Œa€±€Ï… ŽŒº˜ïèH ç¥$h Žçï½5€¤Ë€˜–€˜–€¤Ë€Éj€ô$YYÃô$$ø=b$øÃ=bÃ=bÃ Ž¤Ë€˜–€Éj€ô$Ï…Éj€½5€¤Ë€±€±€Éj€ÛºÉj€ô$Ã$øÃ$ø ŽYÃYô$±€˜–€s÷€€,€Œa€Ûº1-1-Ãô$Yô$[€ 5 5ZZ~6€g€¤Ë€Ï…˜–€±€±€Œa€Ï…€,€I>g€˜–€g€jj= I>I>j 5™H~6€7777¨BUFR&bÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ‚UUUUUUZÖµ­kZÖµ­kZÖµµ­kZÖµ­kZÖµ­kZÖ½ï{Þ÷½ï{Þ÷½ï{Þ÷Æ1ŒcÆ1ŒcÆ1ŒcÎsœç9Îs!B„!BŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUTUUUEPQUUUUUUUUUUUð asú—€0Ô¤Ë ŽáÔ€Œa€Us€,€a¨g€s÷€= Œa€s÷€= 0Ô±²~7 ‚7 ‚7 ú—ú—s€…€ja¨YÕŸ€˜–€€,€s÷€g€UsI>a¨Œa€Éj€Éj€±€¤Ë€ 5js÷€j€…€…ú—€UsŒa€±€a¨0Ô 50Ô$Ÿ±€¤Ë€s÷ ŽÉj€s÷€˜–‚7 € 50Ô= j+Ä+Ä~±²~7 ú—‚±²+Ä~±²~±²|j 5+Ä|= = ˜–€±€±€½5€˜–€ÕŸb=b½5€I>0Ô0Ô= ½5YY½5€a¨a¨s÷€Œa€Éj$ø Žçï$ø=b$øç€a¨= 5$ŸI>½5€±€¤Ë€˜–€s÷€I>$Ÿ77775€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUTUTUTUUUUUUUUUUUUUUEUUUUð `j$ŸI>Œa€çïáÔ€½5€˜–€¤Ë€s÷€Usa¨0Ôg€€,€ÕŸ€áÔ€ÕŸ€Œaƒ+Ä+Ä| 5±²+Ä|I>Éj€çï0Ôa¨a¨a¨= $Ÿ+Ä| 5j0ÔI>a¨s€…ú—ú—€…€…€±²|0Ա̺UÌŒº1-$øçïçï½5€¤Ë€ô$1-Œº1-€,€€,€Éj€±€¤Ë€áÔ$øŒº‚²¥$€çïÉj€áÔ€½5€½5€¤Ë€€,€I>= I>€,€€,€s÷€s÷€s÷€Œa€a¨Usa¨Œa€˜–€˜–€ÕŸ€çïáÔ€Œa€I>I>= Usj+Ä|$Ÿa¨Œa€Éj€½5€¤Ë€˜–€Œa€Œa€€,€½5€ô$$ø Žçï±€g€= 7777ïBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Ý¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc]Êt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUTUUUUEUUUUPUUUUUUð `= a¨= 57 ‚±²~±²|0Ô±€çïÕŸ€½5€çï½5€½5€ÕŸ€áÔYYY ŽÃ$øý5€g€= j0ÔjŒa€±€½5€±€g€Usg€I>€,€½5€Éj€ô$UÌUÌI—Y±€€,€I>0Ô+Ä~±²~7 ‚±²|a¨Œa€Œa€I>a¨I>= Us 5 5I>€,€ô$ç€€,€ 5ú—€j$Ÿg€j0Ôs÷€s÷€s÷€s÷€a¨Usa¨ô$áÔ€áÔ€ô$gƒ+Ä}€…€…sú—‚7 €…ú—€€,€˜–€˜–€a¨$ŸI>a¨˜–€Éj€½5€ÕŸ1- ŽÕŸÃô$Œa€a¨ 5j 5j= ½5€ÕŸ€7777ïBUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ40I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUT@QUUTð `±YY½5€Usg€€,€I>s÷€¤Ë€áÔ€Œa€a¨$Ÿa¨€,€= = Us€,€¤Ë€ÕŸ€áÔ€áÔ€çï±€€,€UsUss÷€g€g€g€ç€…€…n6n6I—UÌ=b$øô$ÕŸ€ô$áÔYI—I—YÕŸ€±€±€ÕŸÃ1- Ž=b=bäËÀ,€= a¨$Ÿ$ŸI>= I>˜–€€,€a¨g€a¨Us= = = $Ÿ±²|7 ú—€…s€…ssú—ú—‚7 ‚±²|$Ÿ+Ä|$Ÿj+Ä|$Ÿ$Ÿ$ŸI>$Ÿ0ÔI>+Ä|ú—ú—€…ú—‚±²|+Ä+Ä|jj$Ÿj+Ä|7777ïBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀH0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ð‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUTUUUPUUUUUUUUUUUUUUUUð ` 5g€= +Ä+Ä|$ŸjI>Us¤Ë€g€ÉjÃÃÃYUs±²~±²|$Ÿ$Ÿ$Ÿ= ±=bô$±€= I>= 5j+Ä+Ä| 5I>€,€€,€Us= = jj 5jjUsUss÷€0Ô 5+Ä~7 ú—‚7 ú—ú—ú—‚7 ‚±²| 5Œa€€,€a¨I>= = 0Ôa¨˜–€¤Ë€±€˜–€€,€±€˜–€±€˜–€˜–€Œa€€,€Œa€€,€Œa€€,€˜–€€,€s÷€s÷€˜–€¤Ë€çï$øUÌ$ø1-=b1- ŽÉj€ÕŸ€áÔ€áÔY½5€UsÉj€ô$çïÕŸ€áÔ€½5€Éj€áÔYô$ ޽5€çï$øÃI—Ã1-çï7777ïBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ`0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Ûm¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž…±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUTQUTUUUUTUUUUUPUUUUUUUð aY$øçïÕŸ€= g€g€0Ô= Usg€Us€,€g€€,€˜–€¤Ë€±€g€I>0Ô= 0Ô$Ÿ 5±²}ú—€…‚7 ‚±²~±²|+Ä+Ä| 5j+Ä|j0Ô$ŸjI>0Ô$Ÿ 57 ƒ+Ä~±²~7 ‚±²|g€áÔ€½5€±€s÷€a¨UsjUsa¨= = Usg€= j±²~7 ƒ+Ä|$Ÿa¨Œa€˜–€Œa€s÷€Œa€˜–€€,€˜–€˜–€Éj€ÕŸ€áÔ€ÕŸ€¤Ë€¤Ë€€,€s÷€Œa€Us 5±²+Ä|a¨ÉjÃçïáÔ$øY½5€çïáÔ€áÔI—n6˜ïI—1- ŽÃ$øô$áÔ€áÔYÃn6ÉÃ1-7777ïBUFR&bÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÂUUUUUUUUUUUUUUUU^sœç9Îsœç;Þ÷½ï{Þ÷½ï{Þ÷½ï}ï{Þ÷½ï{Þ÷½ï{Þ÷€„!B„!B„!D!B„!B„ Š¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUEUUUUUUUUUUUUUUAUUUUUUUUUð `çïÕŸ€Éj€˜–€˜–€¤Ë€½5€˜–€˜–€Œa€˜–€Us0Ô 5j+Ä|$ŸUsÉj€çïçï¤Ë€€,€Us0Ôs÷€g€s÷€€,€ÉjI—=b=b$ø½5€a¨$Ÿ+Ä~7 ‚±²| 5g€s÷€g€= 0Ô$Ÿ$Ÿ$ŸI>I>I>g€˜–€¤Ë€€,€Œa€s÷€0Ô 5I>I>$Ÿ$ŸUsŒa€s÷€I>±²|j$Ÿ= jI>I> 5$Ÿ€,€˜–€Usj±²~±²|UsI>Us= Œa€Œa€¤Ë€¤Ë€˜–€˜–€s÷€½5€ÕŸ€ô$ ŽáÔ€Éj€½5€çïô$˜–€0Ôj±²|Us¤ËY$ø±€€,€€,€Œa€Œa€€,€˜–€ô$±€çï77775€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ 0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðU@UUUUUUUUUQUUUU@UUUTEQQETð `áÔ€½5€Us$Ÿú—€…€…€Œa€…ú—‚±²|$Ÿa¨a¨€,€˜–€Us$Ÿ0ÔjI>0ÔI>a¨a¨I>0Ôj 5UsI>$Ÿa¨s÷€ô$Yô$çïáÔ€ÕŸ€±€¤Ë€±€çïÕŸ€= I>= +Ä|0Ô+Ä+Ä}€…€= +Ä~±²+Ä|0Ô½5€¤Ë€Éj€ÕŸ€¤Ë€ÕŸ€˜–€±€¤Ë€˜–€½5€ô$s÷€s÷€j$Ÿ0Ô±²~±²+Ä+Ä~7 ‚±²|a¨g€g€a¨UsUs¤Ë€g€= s÷€s÷€I>g€$Ÿ±²|j+Ä| 5j$Ÿ+Ä|$Ÿ0Ô 5±²| 50Ô+Ä|7 €j+Ä|g€±€= j7 ‚±²~±²~±²~±²|7777ÔBUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ$0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥µÏ„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUUEUUUUUUUUUUT@TUUð b±²|j$Ÿ¤Ë€±€ÕŸYÉj€€,€g€˜–€ÕŸ€€,€g€g€a¨= Usa¨$Ÿj7 ‚7 ƒ+Ä}ss‚7 €0Ôs÷€¤Ë€˜–€Œa€±€½5€€,€Œa€s÷€g€a¨a¨a¨s÷€$Ÿ$Ÿj+Ä|I>j$ŸŒaYÃYÉj€¤Ë€˜–€s÷€Œa€ô$ô$YYYUÌb=bÉj€jj0Ô= ¤Ë€ÕŸ€áÔ€¤Ë€Éj Žç€±€±€½5€ÕŸ€áÔ€a¨I>$Ÿ 5jú—‚7 ú—ú—ú—‚7 ‚7 €0Ô= 7 ‚7 ‚7 ‚±²~7 ú—‚±²+Ä|= I>UsÕŸ€Us±²~±²|= $ŸI>a¨$Ÿa¨Œa€˜–€s÷€€,€7777ÔBUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ80’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUA@UUU@UUUUUUUU@UUUUUUUUUUð `˜–€˜–€s÷€€,€$Ÿg€I>jj+Ä+Ä|±²+Ä+Ä~7 ú—€…‚7 ú—ú—ú—‚±²~±²}ú—‚7 ú—‚7 ‚±²| 5= a¨¤Ë€¤Ë€$Ÿj$Ÿ0Ô0Ô= = 0Ôj+Ä~±²+Ä+Ä+Ä| 5 5jj0ÔUsÉj€Œa€Éj€€,€Us$øÉj€áÔ€áÔ€áÔ€çï Žô$€,€I>= I>= $Ÿj$Ÿ 50Ô= jI>€…‚7 ƒ+Ä| 5= ˜–€Éj€ÕŸ€s÷€Œa€˜–€˜–€s÷€s÷€g€s÷€¤Ë€€,€g€½5€½5€¤Ë€Œa€Œa€a¨Œa€= I>Œa€çïáÔ€½5€€,€g€Usg€Œa€g€s÷€±€ÕŸ€¤Ë€€,€7777ÔBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑL0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛnÛ`‹:Zà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èRØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUQUUUTAUUUUUUUUUUUUUð `çï½5€= I>0Ôg€I> 5I>g€՟€Éj€˜–€€,€g€±€¤Ë€Œa€s÷€€,€g€UsUs¤Ë€¤Ë€s÷€g€s÷€¤Ë€˜–€a¨Us¤Ë€±€ô$Éj€Œa€= +Ä|0Ôg€Œa€I>€,€Œa€¤Ë€Œa ޽5€s÷€a¨UsI>a¨Us+Ä+Ä+Ä| 5±²|7 € 5±²~±²|jj0Ôjj+Ä+Ä+Ä~±²~7 € 5±²| 50Ԥˀô$çïÉj€˜–€çï¤Ë€g€g€€,€Œa€±€˜–€ô$¤Ë€€,€g€Œa€Œa€a¨a¨$ŸI>a¨±€¤Ë€Œa€˜–€€,€Usg€€,€ÕŸ€áÔ€áÔÃI—Ãô$ÕŸ€¤Ë€= s÷€j 5$Ÿ7777ÔBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñd0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUU@PUUU@UUUUUð `€,€ÕŸ€Éj€ô$Œa€€,€g€˜–€¤Ë€˜–€ÕŸ€ÉjYÕŸ€a¨a¨€,€±€I>Uss÷€çï±€áÔY$øY±€˜–€€,€s÷€s÷€€,€Œa€¤Ë€€,€ÕŸÃtP$ø$øn6˜ïb1-Y½5€Éj€áÔ1- Ž$ø1-áÔ€±€Éj€¤Ë€±€ÉjUÌ€…UÌI—Y±€±€a¨I>±²+Ä+Ä~±²|j 5 5+Ä+Ä|0Ôj 50ÔUsÕŸYŒa€Usj±²~7 ‚7 ‚7 €= = +Ä~7 ú—‚±²}ú—‚±²}ú—‚7 ‚±²| 5j0ÔÉj€±€g€€,€€,€a¨¤Ë€çïáÔ=b€… ŽÉj€¤Ë€s÷€a¨Œa€7777ÔBUFR&bÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑUUUUUUUUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷ B„!B„!B„"„!B„!B„!CÆ1ŒcÆ1ŒcÆ1Œd!B„!B„!@Š×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUTPUUUUUUUUUUUUUUUUUUUUUEð `€,€I>s÷€¤Ë€¤Ë€€,€Œa€áÔ Ž½5€¤Ë€g€I>7 ‚±²| 5= s÷€Us0Ôj 5±²}ú—€7 ‚±²| 5+Ä~±²~±²+Ä+Ä}ú—‚7 ú—ú—€ 5Usg€0Ôg€0Ô 5 5j€,$ø ŽçïYô$˜–€±€a¨ô$b½5€˜–€Œa€¤Ë€¤Ë€çï Ž Ž$ø$øÃŒºn6$ø ŽÕŸ€½5€ÕŸ€Éj€¤Ë€Éj€çïÕŸ€ÕŸ€¤Ë$øô$ Ž Žçïô$ç€Usg€Us¤Ë€g€I>€,€= YŒa€g€±€˜–€Œa€Us€,€˜–€Œa€±€a¨½5€Éj€a¨0ÔI>I>= a¨I>0Ô$Ÿ+Ä|$Ÿ77775€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUP@PUUUUUU@UQUU@UUUUUUð `I>I>0Ô$Ÿ$Ÿ±²~±²~±²~±²~±²}ú—ú—€…ú—ú—‚7 €…ú—ú—‚7 ‚±²|jj+Ä~±²~±²~7 ‚±²~±²| 5±²}ú—ú—ú—ú—€…ú—ú—ú—‚7 ú—‚7 ƒ+Ä| 5I>I>Us$Ÿa¨= Éj€¤Ë€s÷€áÔ=b½5€±€½5€¤Ë€Œa€áÔ1-$øŒa€Us= €,€0Ô 5±²~±²~±²~7 ‚7 ƒ+Ä| 5Us€,€a¨I>g€I>+Ä| 5$Ÿjs÷€a¨= 0Ô= 0Ôj±²+Ä+Ä~±²+Ä|= ˜–€Éj€ÕŸ€±€Œa€s÷€a¨I>= = $ŸUsUsUss÷€±€˜–€˜–€Us= Us0Ô$Ÿ0Ôs÷€7777a€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@,0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUU@UQTUUUUUUU@UUUUUUUð `˜–€¤Ë€s÷€€,€€,€a¨$Ÿ 5 5= = UsUsŒa€Éj€½5€ÕŸ€Œa€a¨= I>$Ÿ= I>g€g€0Ôú—‚7 ú—‚±²~±²~7 ‚±²|j= g€= $Ÿ+Ä|$Ÿ 5j 5+Ä+Ä+Ä~7 ‚±²+Ä~±²~7 ‚±²}ú—‚7 ‚7 €js÷€¤Ë€I>Us0Ô0Ôjj 5$Ÿs÷€Éjà ŽáÔ€áÔ€ô$YáÔ€s÷€Œa€Œa€¤Ë€a¨UsI>j 5±²~±²~±²+Ä~±²| 5UsÕŸ€Éj€ÕŸ€Éj€Éj€¤Ë€€,€Usg€˜–€a¨I>j$Ÿ0Ôj+Ä+Ä+Ä~±²|0Ô½5€ÕŸÃÃç€s÷€s÷€˜–€7777a€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUU@UUUUUUUUUUUUTPUUUPUð `€,€ÕŸ€s÷€I>¤Ë$ø Žô$ô$s÷ƒ+Ä+Ä}€…sú—€ŒaY ŽÕŸ€áÔ€¤Ë€s÷€Éj€çï½5€áÔ€˜–€= +Ä~±²~±²+Ä}€…€…‚7 €…sú—€jg€s÷€a¨$Ÿ0ÔI>0Ô0Ô= Usg€I>Usg€Us$Ÿj$ŸI>$Ÿ 5I>g€€,€˜–€˜–€g€g€g€a¨Uss÷€a¨I>$Ÿ$Ÿs÷ Žô$s÷€I>s÷€= $Ÿ 50Ôa¨Usa¨= +Ä~±²+Ä|$Ÿ+Ä|$Ÿj+Ä+Ä|$Ÿ$Ÿ±$ø½5€Œa€ 5 5+Ä| 5g€՟€½5 Ž$øçïa¨+Ä~7 ‚7 €+Ä~7 €0Ôs÷€a¨Us7777a€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@T0 $’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹k€" c¡+c\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTQUUTUTPQP@UUUUUUUUUð ` 50ÔÉj€s÷€˜–€Éj€½5€Us+Ä~±²~7 ƒ+Ä~±²~±²|+Ä|j$Ÿ+Ä|= $Ÿ$Ÿ= 0Ô= ˜–€½5€¤Ë€Us±²~7 ú—‚±²+Ä~±²~±²~±²+Ä|Usj= 0Ôjj+Ä+Ä|$ŸI>s÷€€,€a¨±²~±²~±²~7 ‚±²+Ä| 5+Ä| 5±²~7 €…sú—€Œa€O€…ú—€$Ÿ±²~7 ‚7 ‚±²~±²+Ä|0Ô 5j$Ÿ= = = ÕŸ1-$ø Ž=bÉj€¤Ë€Œa€s÷€¤Ë€±€€,€$ŸUs 5j= $Ÿ0Ô 5Œa€½5€áÔ€¤Ë€±€¤Ë€g€I>$Ÿ±²+Ä~±²| 57777a€BUFR&bÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑBUUU]kZÖµ­kZÖµ­o{Þ÷½ï{Þ÷½ï{Þ÷½óœç9Îsœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{ÞûÞ÷½ï{Þ÷½ï{Þ÷½ïŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUQ@@QUUUUUQUUUUUTUUð `0Ô$Ÿ 5 5jjj 5 5jjj+Ä|j±²}ú—‚7 €…€…€Œa€…€…ú—ú—€…€…€…€…ú—‚7 ‚7 ‚7 ‚7 ‚7 ƒ+Ä|= jj7 ‚7 €…ú—‚±²|$Ÿj+Ä+Ä+Ä+Ä|+Ä|j= +Ä|0Ô€,€Œa€ 50Ô 5j$Ÿg€˜–€€,€$Ÿ$ŸI>= jj 5$Ÿ= +Ä| 5±²|j±²+Ä+Ä|j+Ä|jja¨€,€g€Us0Ô= = = $ŸI>$ŸUsj 5 5$ŸUs0Ô 5$Ÿj+Ä~±²~±²+Ä|jI>= $Ÿ= $Ÿ= 0Ôj77775€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc_Êt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUDUUUUUTUUUUUUUUUUUUUUUUPð `I>I>$Ÿ 5j+Ä|±²}ú—‚7 ú—s€Œa€…ú—€ 50Ô$Ÿ 5j0Ô 50Ôj$ŸUsg€0ÔjI>a¨0Ôj 50Ô= +Ä+Ä}€…ú—s€…s€…ú—ú—ú—ú—‚±²~7 ‚7 ‚±²|j 5+Ä~±²}ú—‚7 ú—€$Ÿg€s÷€UsUsI>= = 0Ô0Ô$ŸI>I>j$ŸI>Us$ŸjÉj€çïÕŸ€Éj€±€˜–€¤Ë€¤Ë€Œa€s÷€I>0Ô$Ÿ= a¨±€˜–€€,€áÔUÌI— Ž$Ÿa¨½5€0ÔUss÷€Œa€Usg€a¨0ÔI>0Ô$Ÿ 50Ôa¨a¨I>j= 0Ôú—ú—€7777ŸBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUUUUUUQTUTUUUUUUUð a€…‚7 €…ú—€ 5a¨$Ÿj$Ÿ 5+Ä|= = $Ÿ$Ÿ0Ôj 5$ŸUs0Ôs÷€½5ƒ+Ä|$Ÿ 5$ŸI>I>UsUs= 0Ô= UsUs$Ÿ= = I>j$Ÿ0Ôg€˜–€ÕŸ€áÔ€çï½5€¤Ë€€,€€,€˜–€Œa€€,€s÷€a¨$Ÿ 5= a¨js÷€0Ô$Ÿ$Ÿa¨= 0Ô+Ä|= j$Ÿ 57 ‚±²}ú—ú—ú—‚7 ƒ+Ä|7 ‚7 ‚7 ‚7 ‚7 ú—‚±²~±²| 5$Ÿa¨$Ÿ0ÔUs0Ô+Ä|= g€€,€a¨Usa¨g€˜–€a¨Usa¨a¨UsUsUsg€UsUs0Ôj$Ÿj 5Œa€Éj€½5€7777ŸBUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€00I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTUUUUUTUUUUUPUUUUT@QUUPQð `€,€g€s÷€UsŒa€˜–€€,€a¨g€$Ÿ= 0Ôg€$Ÿ±²+Ä+Ä|j$Ÿ= g€Éj€áÔ€Éj€±€Œa€g€$ŸŒa€áÔ€áÔ Ž±€€,€Œa€g€Œa€s÷€Œa€ja¨ 5+Ä|$Ÿa¨€,€g€a¨˜–€I>I>I>= s÷€Us¤Ë€˜–€˜–€I>0ÔI>j 5 5$Ÿ+Ä~±²+Ä|¤Ë€˜–€g€Us= 0ÔUsUsI>I>ô$áÔ€¤Ë€˜–€Éj€áÔ€¤Ë€0Ô 5±²~±²+Ä|j0Ô$Ÿ±²+Ä+Ä|j0Ô7 €Usa¨= j 50ÔI>$Ÿ 5j±²+Ä~7 ‚7 ‚7 ‚7 ‚7 ‚±²| 5 50Ô+Ä|7777ŸBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€D0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm»`‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ކ5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUTUUUUTUUUUUUU@@ð `$Ÿj+Ä|0Ô= 0ÔI>= = = s÷€˜–€±€½5€˜–€I>g€a¨= a¨a¨˜–€˜–€˜–€Éj€±€˜–€½5€¤Ë€Œa€˜–€Éj€½5€˜–€˜–€˜–€¤Ë€Œa€¤Ë€±€±€Œa€Uss÷€€,€¤Ë€€,€s÷€€,€s÷€±€áÔ€±€g€ 5$Ÿ±²+Ä|= çïáÔ€€,€Œa€±€g€€,€= = UsI>$Ÿ$Ÿa¨UsUsg€= €,€Us+Ä| 5Usg€s÷€Œa€g€a¨UsI>= I>I>a¨= 5 5= UsI>= = = $Ÿa¨0Ôg€Usg€= +Ä+Ä~±²+Ä+Ä~±²~±²~7 ƒ+Ä| 5jI>7 ‚±²}€…€7777ŸBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€\0’I$’I$’I)$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@UUUUUTUUUUUEUEUUð ass€…‚±²}ú—€Œas€Œa€…s€…‚7 ‚7 ú—ú—€…ƒ+Ä+Ä~±²| 5+Ä+Ä+Ä+Ä+Ä~±²~±²|$Ÿ= I>j 5±²~±²~7 ƒ+Ä|¤Ë=b Žô$ÕŸ€˜–€a¨€,€˜–€±€ÉjYI>Usg€ 5= ±²~±²~±²|7 ‚±²~7 ‚7 ƒ+Ä+Ä~±²+Ä| 5 50ÔI>jj±²~±²+Ä+Ä| 5j 5j0Ô$Ÿ$Ÿ$Ÿ±²}€…ú—‚±²|$Ÿ½5 Žçï€,€j 5 5 5+Ä| 5 5$Ÿ 5$Ÿ 5+Ä|0Ô$Ÿ= UsUsj= $Ÿ7777ŸBUFR&bÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ‚UUUUUUUUUUUUUUUUU]ï{Þ÷½ï|ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷ B„!B„!B„"„!B„!B„ Š×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTUUUUTP@UUUUUUUUUPð `0Ô$Ÿ 5+Ä~±²+Ä|= ½5€˜–€Œa€jj0Ôj+Ä|$Ÿ= UsI>0Ô= UsI>$Ÿ$ŸI>Us€,€a¨g€a¨a¨a¨Us+Ä|+Ä~±²~7 ƒ+Ä+Ä~7 ‚±²+Ä|j7 ú—‚±²~±²~±²}ú—‚7 ‚7 ‚±²~±²| 5$Ÿ±²|j7 ‚±²+Ä}ú—‚±²|$Ÿú—€…ú—€…‚±²}ú—‚7 ‚7 ‚±²+Ä| 5$Ÿ= Usj$Ÿ= g€g€g€¤Ë€s÷€= a¨UsI>I>I>g€I>€,€˜–€$Ÿ= I>$Ÿ 5 5 5 5j0ÔI>a¨s÷€UsI> 5+Ä+Ä~7 ‚±²~7 €7 ‚7 €77775€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ 0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUPUUUUP@UUUUUUUUUPQEP@ð c+Ä+Ä+Ä~±²+Ä|jI>Usa¨= I>Us$Ÿ 5±²+Ä~±²|+Ä+Ä+Ä| 5 5 5= UsI> 5= 5= g€s÷€Œa€€,€€,€˜–€a¨±²|+Ä|+Ä| 5j$Ÿj±²+Ä| 5±²~±²~±²+Ä| 5$Ÿa¨Œa€˜–€€,€€,€I>0Ôjj7 €$Ÿ½5€€,€0Ô= 0Ô$ŸI> 5$Ÿ0Ô0ÔUsUss÷€Œa€s÷€ÕŸ ŽÕŸ$øtP=b½5€ô$Éj€ÕŸ€çï±€g€$Ÿ$Ÿ 5±²}ú—ú—ú—‚7 ‚±²+Ä~±²+Ä+Ä|0Ô+Ä| 5 5+Ä|0Ôj 5jú—‚7 € 5+Ä~±²+Ä|7777jBUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ$0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUTAUUUTUUEQTEUUUUUUUUð ` 50ÔI>= $ŸI>a¨s÷€Usa¨s÷€€,€s÷€g€€,€€,€$Ÿj 5ú—€ 57 ƒ+Ä|$Ÿ= ˜–€g€Usj0ÔI>s÷€UsI>0Ô0Ô7 ‚7 ‚7 ‚±²|jg€€…‚7 s€…€Œaú—ƒ+Ä| 5 50Ô 5$Ÿ+Ä}ú—ƒ+Ä~7 ‚7 ú—ú—ú—ú—‚7 ú—€±²}ú—‚±²+Ä| 5= I> 5+Ä|+Ä|±²|j= 5+Ä|j= = +Ä|+Ä|jI>= I>a¨Éj€½5€Œa€a¨s÷€€,€s÷€= I>= a¨¤Ë€¤Ë€ÕŸ€Œa€Us€,€0Ôj0ÔI>a¨$Ÿ 50Ô$Ÿ= 0Ô7777jBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ80$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS SçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UQUEPEUUPUUUDUUUUð `I>= 0Ôj±²~±²| 5I>= $Ÿ$ŸI>= j 5€…€…€Œaú—€…€…sú—€…‚7 ‚7 ú—ƒ+Ä| 50ÔUsI>j 5I>j+Ä|I>s÷€€,€g€$Ÿ+Ä|g€0Ôs÷€$Ÿ±²+Ä+Ä+Ä~±²~±²+Ä~7 ‚7 ‚±²| 5+Ä|j= $Ÿ 5 57 ƒ+Ä| 5 50Ôg€= j±²~±²~7 ú—s‚±²}ú—€…‚±²| 5g€½5€s÷€g€Us= a¨Œa€s÷€Œa€€,€g€+Ä| 5±²~±²~7 ‚±²|±²+Ä+Ä|a¨˜–€Œa€˜–€˜–€€,€g€Œa€Uss÷€a¨g€0ÔI>g€˜–€7777jBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀL0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUU@UUUUPUUUUUUUUUUUUPUð `¤Ë€¤Ë€Œa€˜–€€,€€,€s÷€a¨g€s÷€g€I>UsŒa€g€I>Œa€g€g€¤Ë€Œa€a¨s÷€$Ÿ+Ä~7 ‚±²~±²~7 ‚7 ú—€0Ô$Ÿ$ŸI> 5 50Ô 50ÔUs= UsŒa€a¨s÷€˜–€I>ú—ƒ+Ä~7 ‚±²}€…€Œaƒ+Ä|$Ÿú—€…ú—ú—‚7 €…ú—ú—ú—ƒ+Ä~±²|$Ÿ$ŸUs€,€Œa€˜–€€,€s÷€a¨a¨g€s÷€s÷€= I>0Ôj 5= = a¨0ÔÉj€¤Ë€I>I>$Ÿ0Ô$Ÿ€,€¤Ë€˜–€˜–€s÷€g€Œa€s÷€= 0Ô0Ô$Ÿ$Ÿ$ŸI>I>±€˜–€g€a¨€,€¤Ë€Us±²~±²| 5g€Œa€g€7777jBUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀd0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQPUUUUUUUUUUUUUUUUUUUTPPUUð c+Ä|j$ŸjI>= ±²|$Ÿ0Ô±²+Ä| 5j$Ÿ$Ÿ+Ä~±²~7 €+Ä|j= €,€±€ÕŸ€áÔ€I>$Ÿ 5$ŸI>I>s÷€g€I>€,€çïô$tPI—1-ÃI—çï¤Ë€Œa€s÷€½5€±€Éj€Éj€áÔ€çïÉj€±€Œa€±€a¨0ÔI>˜–€çïçïô$½5€Œa€Éj€½5€±€˜–€¤Ë€±€¤Ë€g€UsI>I>0Ô= 0Ô= 0ÔI>$Ÿ$Ÿs÷€çï$øÕŸØ–€¤Ë€a¨= = s÷€ÕŸ€I>+Ä|0Ô+Ä~±²+Ä~±²~±²~±²| 5+Ä~±²~±²+Ä~±²~7 ƒ+Ä+Ä|$Ÿ0Ôa¨€,€€,€0ÔI>a¨0ÔI>7777jBUFR&bÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÂUUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷Þ÷½ï{Þ÷½ï{Þ÷½ï!B„!B„!BˆB„!B„!B„! cÆ1ŒcÆ1ŒcÆ0ŠçÂ2+k€" c¡Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUQUUU@UUUPUUUUUUUUUUUUUUUUð `Us= I>= ±²|$Ÿ= $Ÿ$Ÿ= Usg€$Ÿ+Ä|I>0Ô$Ÿ= = = = = = $Ÿa¨I>0Ô±²~7 ú—ú—€…‚±²~7 ‚±²~±²|UsŒa€a¨= = I>= = jjI>ÕŸ€a¨g€€,€I>+Ä~±²~±²}ú—ƒ+Ä+Ä}€…ƒ+Ä| 5$Ÿ€,€a¨$ŸUsUs= €,€0ÔI>I>UsI>0ÔI>ç€±€Œa€€,€= = j= ½5€½5€Œa€±€½5€s÷€¤Ë€s÷€I>a¨˜–€s÷€Œa€ÕŸ€áÔ€€,€I>$ŸI>g€Œa€Œa€g€Usg€Œa€$Ÿ$ŸI>s÷€j$ŸI>g€= a¨€,€Us€,€Éj€½5€77775€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUU@QUUUUUUUUUUUð `˜–€±€˜–€g€I> 57 ú—ú—ú—‚7 ‚±²~7 ú—‚±²~7 ‚±²~7 ‚±²|I>¤Ë€½5€ 5€,€jŒa€g€0Ô$Ÿ0Ôj= a¨a¨= 0Ô 5 5+Ä|$Ÿa¨Us+Ä~7 ‚±²~±²~±²~7 ƒ+Ä~±²+Ä|jjI>I>Usg€= $Ÿ= = $Ÿs÷€$Ÿa¨˜–€s÷€Us0Ô7 ‚7 ú—‚7 ú—‚±²|$Ÿ 5+Ä| 5$Ÿg€I>$Ÿa¨Usg€€,€˜–€0ÔUsŒa€0ÔUsI>I>I>I>g€€,€I>0Ô€,€g€a¨€,€˜–€ÕŸ ޱ€Us±€½5€UsI>= $Ÿ$Ÿ 5$Ÿ= Us7777€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ(0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUQUUUUUUUPUUUUQUUUð `UsI>= 0ÔUsUsa¨= j$Ÿ0Ô= ±€ô$ô$Éj€Usg€½5€Œa€a¨= I>UsI>UsUs= = = = $Ÿjj= Us= +Ä|+Ä}ú—ú—ú—€Œas€…ƒ+Ä|jj 5 5 5 5 50Ô$Ÿ±²|j 5 5±²}s‚7 €…ú—ƒ+Ä|jj€,€I>$Ÿ 5 5$Ÿ$Ÿ 5Usa¨= a¨Œa€€,€g€a¨Us+Ä}€…‚7 € 50Ô= g€a¨a¨= $Ÿ= g€a¨Uss÷€gÂÃÉj€I>s÷€Us= I>+Ä|UsÕŸ€¤Ë€çïáÔ€ÕŸ€˜–€¤Ë€€,€g€€,€Us7777€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ<0I$’I$’I$”’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)ކ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUU@UUTUUUUð `Œa€g€g€UsŒa€€,€s÷€a¨Us= €,€g€a¨g€g€= s÷€$Ÿ 5= I>s÷€= = Usg€½5€±€Œa€a¨Us0Ôj= a¨a¨g€g€0Ô= I>a¨ÕŸ€ô$1-½5€˜–€˜–€±€s÷€j$Ÿ$Ÿ= 0ÔUsj±²~±²~±²~±²| 5$ŸI>I>a¨€,€s÷ƒ+Ä+Ä|$Ÿ$Ÿ±²+Ä}ú—‚7 ‚7 ƒ+Ä~7 ‚7 ú—ú—‚7 ‚±²+Ä|j+Ä~±²+Ä~7 €s÷€½5€áÔ€Éj€j±²|+Ä+Ä+Ä|a¨€,€g€0Ôjj+Ä| 5j0ÔI>jgÂY Žô$çïáÔ€Éj€çïŒa€$Ÿ7777€BUFRæbÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑT0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUTUUUUð `$Ÿ˜–€±€¤Ë€¤Ë€s÷€0Ô= I>Us€,€˜–€¤Ë€¤Ë€áÔ Ža¨½5€Éj€Usj0Ô 5 5g€¤Ë€˜–€˜–€½5€a¨Usa¨= UsUs€,€s÷€Œa€€,€˜– Ž=b1-çïçïg€˜–€Œa€Œa€½5€½5€ô$Yçï±€˜–€çïI>j¤Ë€½5€áÔ€ÕŸ€I>gÂ=bÉj€a¨ô$a¨Œa€UsI>Us¤Ë€½5€ÕŸ€ô$ÕŸ€Œa€½5€€,€a¨˜–€s÷€g€¤Ë€˜–€€,€½5€áÔ€çïçïYÉj€Œa€€,€s÷€˜–€ÕŸ€Us 5+Ä|= Uss÷€ 5 5Éj€˜–€€,€€,€s÷€g€s÷€s÷€Us0Ô$Ÿ+Ä+Ä~±²| 5±²~±²| 57 €7777€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñh0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ç>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTTUUUUUUUUUUEUUUUUUUUUUUUUð b7 ƒ+Ä+Ä|j0Ôg€I>I>I>0Ô0Ô0Ô$Ÿj 5+Ä|±²~7 ƒ+Ä+Ä~±²~±²}ú—‚±²+Ä~7 ‚±²|0Ô€,€¤Ë€s÷€g€I>a¨€,€Œa€Œa€g€g€a¨ÕŸ€ÕŸ€ÕŸ€±€Œa€¤Ë€±€g€¤ËY˜–€ŒaUÌ€…˜ïŒºtP€…ÃÉj€Œa€€,Y ŽUÌb€,€$Ÿj0Ô+Ä|UsjUs½5=bb±€$Ÿ= 0Ô= I>I>I>Us¤Ë€ÕŸÃ1- Ž Ž Ž$ø=b1-tPn6=b˜– Ž$ø±€˜–€0Ôj= jj 5= g€a¨s÷€a¨˜–€Œa€˜–€a¨Œa€€,€±€çïô$Éj€7777€BUFR&bÿ« fÑ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_{À!B„!B„!B„B„!B„!B„!cÆ1ŒcÆ1ŒcÆ1Œ„!B„!B„!B¥)JP‹[\ c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUEU@UUUEUUUUQAUUUUUUUUUUEð `Œa€g€g€a¨I>jj= a¨0Ô= UsUsUs0Ôj0Ô= $Ÿa¨+Ä|j$Ÿ€,€jj±²}€…‚±²+Ä~7 s€…ú—‚7 ú—‚±²|j 50Ôa¨$Ÿ€,€áÔ€Éj€s÷€a¨jI> 5+Ä| 5= s÷€€,€s÷€Us$Ÿ$ŸUsg€a¨g€Œa€g€s÷€= a¨= 5 5±²| 57 ‚±²|= ±€˜–€s÷€I>I>g€I>0Ôj$ŸUs= g€Éj€s÷€Us˜–€0ÔUs$ŸUs€,€¤Ë€½5€Éj€Éj€Œa€I>g€€,€½5€±€Œa€g€Uss÷€s÷€j+Ä| 5±²~7 ƒ+Ä|Us77775€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUQUUU@EDQT@UAAUUUUTUUð `±€Œa€€,€= = 0Ô= s÷€= UsI>= g€s÷€g€g€I>I>+Ä|+Ä|+Ä| 5€,€Œa€Usa¨I>$Ÿ$Ÿ= Us0Ôjj 5±²}ú—€…s€Œas‚7 ú—sú—ƒ+Ä|±²| 5 5±²|j±²|+Ä| 5 5 5+Ä+Ä| 57 ú—s‚7 ‚±²}ú—ú—‚7 ú—‚7 ‚±²~7 ‚7 ‚±²+Ä|0Ôa¨g€Usj±²~±²|0Ô 5+Ä+Ä|€,€Œa€Éj€€,€€,€0ÔI>0Ô$Ÿ= UsŒa€¤Ë€€,€= 0Ô= Us 5±²+Ä~±²~±²|0Ô˜–€Œa€g€UsUsI>= = 7777a€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@,0 $’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡+c\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUDUUTUUUU@Uð `a¨€,€€,€€,€g€±€Œa€˜–€Œa€a¨0ÔŒa€¤Ë€s÷€˜–€g€€,€±€¤Ë€I>0ÔUsUss÷€s÷€˜–€g€Us$Ÿg€¤Ë€ÕŸ€0Ô+Ä|+Ä|0Ôa¨g€Usa¨j+Ä|jj±²~7 €$Ÿg€I>a¨j±²~±²|$Ÿ0Ô7 ‚±²|g€€,€½5€˜–€Us= = Us= 0Ô$Ÿ$Ÿ$Ÿ= 0ÔUsUs 5+Ä}€…‚7 ú—‚7 €…ú—€…sú—ƒ+Ä~7 ú—‚7 ƒ+Ä}ú—‚±²+Ä~±²|0Ô0Ô7 €…‚±²~±²| 5±²}ú—ƒ+Ä}ú—ú—‚7 ú—€…‚7 ú—‚7 ‚±²~±²+Ä+Ä~7 ‚±²| 50Ô0Ô= 7777a€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@@0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUTUUUTUUUTQUUUUUUUUUUUUUð `I>UsUs7 ƒ+Ä| 5a¨€,€€,€Uss÷€Usg€a¨a¨s÷€Œa€s÷€0ÔUs$Ÿ$Ÿ+Ä~±²}€…€…ú—ú—ƒ+Ä| 50Ô€,€s÷€g€a¨a¨g€g€a¨˜–€¤Ë€¤Ë€s÷€Us$Ÿ+Ä+Ä}s‚±²~±²}s€…ƒ+Ä|$Ÿa¨s÷€˜–€˜–€g€s÷€Œa€¤Ë€Éj€±€€,€Us= jj+Ä|j+Ä| 50Ô˜–€Œa€¤Ë€±€€,€€,€s÷€˜–€€,€Œa€ÕŸ€áÔ€Œa€áÔ€ô$ô$çïáÔ€a¨0Ô 5 5s÷€Éj€Éj€çï½5€½5€¤Ë€¤Ë€çïŒa€ÕŸ€ÕŸ$ø=b1-1-ÃYÃáÔ€Œa€¤Ë€a¨I>I>g€Us7777a€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ@X0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%KcŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTPQTUUUUUUUUUUUUUUUUUUUUð `˜–€½5€ÕŸ€Éj€€,€g€I>a¨a¨˜–€ÕŸ€áÔ€ô$U̽5€çïÉj€€,€€,€g€Us0Ô±²|j+Ä+Ä|j 5+Ä|+Ä|= j0Ô0Ô$Ÿ+Ä+Ä+Ä| 5±²}€…€I>áÔ€ô$¤Ë€s÷€Œa€= Éj€jçï±€áÔ€±€çï Ž¤Ë€€,€g€g€0Ôg€jg€½51-UÌÕŸ€Us˜–€˜–€½5€áÔ Ž1-n6n6I—I— Žô$Éj€€,€Éj€˜–€Us0ÔŒa€±€çïYÃs÷€I>= s÷€¤Ë€Éj€¤Ë€çïI—$ø ŽáÔ€±€±€Éj€±€˜–€s÷€€,€s÷€±€±€s÷€˜–€Usa¨g€Œa€7777a€BUFR&bÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑBUUUUUUUUUUUU]kZÖµ­ï{Þ÷½ï{Þ÷½ï{Þ÷¾sœç9Îsœç9Îsœç9Î÷½ï{Þ÷½ï{Þ÷½ï{Є!B„!B„!B‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUPUUUUTUUUUUUUUUð `Éj€ÕŸ€˜–€½5€½5€€,€€,€= jI>jjja¨˜–€±€±€g€a¨$ŸjI>¤Ë€g€= Éj€˜–€½5€Éj€¤Ë€s÷€€,€g€ 5±²~±²~7 ƒ+Ä~7 € 5UsŒa€ç€s÷€= $Ÿ= çïtPI—I—$øáÔ€Éj€€,€I>ú—€…€Œa€Œaú—‚7 ‚7 ‚7 ‚±²~±²+Ä|+Ä~±²~7 €…‚7 ‚7 ú—s€…€ 5€…ƒ+Ä|a¨±€˜–€½5€€,€0Ôa¨Œa€s÷€a¨I>= a¨= = = 0Ô= +Ä|€…‚±²|j= Y$øô$ô$g€g€Œa€Œa€˜–€€,€s÷€€,€Éj€±€Œa€¤Ë€Us77775€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€ 0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUQUUUUUTUUUTUUUQ@ð b±²|j 5+Ä| 5s÷€½5€€,€= = = Uss÷€s÷€g€a¨˜– Ž˜–€ÕŸ€g€½5€g€j±²|$ŸI>s÷€çï±€Œa€g€g€Usa¨UsÉjÃô$çïg€s÷€Us$Ÿjj 5 5+Ä+Ä|jUsŒa€€,€€,€Œa€s÷€€,€Œa€¤Ë€Uss÷€Usa¨ 5j= $Ÿ+Ä+Ä| 5+Ä}ú—‚±²|$ŸI>a¨j$Ÿ= 0Ôj$Ÿ0Ô= UsUs$Ÿj$Ÿ±²|j7 €$Ÿ7 ú—s‚7 ú—ƒ+Ä}ú—‚±²~±²+Ä+Ä~±²~±²+Ä| 5±²+Ä~7 ƒ+Ä}ú—ú—‚7 sú—€Œas‚±²~±²|= ¤Ë€7777jBUFRæbÿ« fÑ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€ 0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž…-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUTUUUUTUUUUUUUUUUð `½5€¤Ë€g€I>= a¨g€±€áÔ€ô$$øÉj€Œa€s÷€s÷€= +Ä|±²~±²+Ä|= ˜–€çïÉj€I> 5jjjI>€,€Œa€ÕŸ€Éj€Éj€áÔ€Usa¨a¨$Ÿ0Ô 5 5$ŸUs˜–€Éj€¤Ë€Œa€€,€a¨Œa€Œa€˜–€˜–€Éj€¤Ë€Œa€s÷€I>$Ÿ 57 ƒ+Ä~7 ‚±²+Ä|$Ÿ€,€ÕŸ€½5€g€= $Ÿ= 0Ôa¨€,€±€±€˜–€s÷€s÷€g€j 5±²|I>jI>˜–€ô$çïñ€½5€½5€ÕŸ€±€áÔYÃ=b1-$ø Ž Ž ŽYÕŸ€Éj€±€¤Ë€s÷€Œa€Œa€˜–€€,€áÔ ŽÉj€¤Ë€a¨a¨I>s÷€7777jBUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€40I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUTPUUUUUUUUUUUUUUUUUUUUUUUð aYÉj€áÔ€¤Ë€±€g€¤Ë€˜–€a¨= $Ÿ= I>Œa€Œa€s÷€g€€,€Œa€¤Ë€Œa€€,€s÷€= 0Ô$Ÿ$Ÿj= s÷€ú—€±²+Ä| 5s÷€˜–€€,€a¨s÷€a¨a¨a¨˜–ÃYs÷€= €,Ã$øô$¤Ë€UsI>I>$Ÿa¨ÕŸYÕŸYáÔ€Éj€s÷€Œa€˜–€˜–€±€Œa€Œa€a¨g€Usg€I>g€a¨g€s÷€a¨Usg€Œa€¤Ë€½5€€,€g€I>a¨= = = a¨g€= I>€,€½5€Éj€±€s÷€˜–€0Ô0Ô0ÔI>a¨½5$øI—ÕŸ€±€˜–€Éj€½5€áÔ=bn61-½5€±€½5€Œa€Œa€g€7777jBUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€L0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUT@UUUUUQUUUUUPð `Œa€a¨g€a¨a¨ÕŸ€ô$ÕŸ€a¨€,€€,€I>I>0Ôa¨¤Ë€˜–€s÷€g€g€a¨Œa€Œa€g€¤Ë€˜–€s÷€s÷€˜–€¤Ë€s÷€s÷€UsUs±€½5€±€±€€,€½5 ޱ€ÕŸ€±€¤Ë€½5€±€Œa€Éj€Œa€= 0Ôj$ŸI>a¨g€¤Ë€¤Ë€€,€s÷€g€Œa€g€g€UsI>Us$Ÿ$Ÿ= +Ä|0Ô±²}ú—ƒ+Ä|= Œa€½5€Éj€áÔ€áÔ€áÔ€ÕŸ€ÕŸ€±€ÕŸ ŽÕŸ€±€˜–€½5€˜–€¤Ë€Œa€a¨0Ô 5+Ä|s÷€Éj€ÕŸ€Us€,€g€¤Ë€¤Ë€¤Ë€Uss÷€½5€ô$Éj€áÔ€½5€€,€€,€0Ô$Ÿ 5±²}ú—ƒ+Ä|UsÕŸ€½5€7777jBUFRæbÿ« fÑ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ€`0’I$’I$’I)$’I$’I$’m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ•-Ž|#)Ò¶¸!¦:¶5Ï„e:V×D2˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUT@UUUUUUUUUUUUUUUUUUUUUð `±€˜–€g€g€¤Ë$øY1- ŽçïçïÉj€UsI>a¨a¨I>$Ÿg€¤ËYô$ô$ô$¤Ë€˜–€½5€¤Ë€¤Ë€½5€˜–€a¨= $Ÿ 5+Ä|+Ä~±²~±²~7 € 5ÉjÃ1-áÔ€˜–€s÷€Œa€€,€g€€,€˜–€áÔ ŽÕŸ€½5€¤Ë€Éj€Œa€I>$Ÿj 5$ŸUs½5€½5€¤Ë€0Ô0Ô= j0Ô€,€ô$=b1-I—YYçïÕŸYÕŸ€s÷€g€¤Ë€¤Ë€±€½5€€,€I>= Us= I>g€s÷€ô$1-$ø$øYô$çïô$˜–€s÷€a¨I>= g€áÔ€çïô$ô$çïÕŸ€±€¤Ë€I>Us±€½5€Œa€a¨7777jBUFR&bÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ‚UUUUUUUUUUUUUUUUUUU^sï{Þ÷½ï{Þ÷½ï{Þ÷¾÷½ï{Þ÷½ï{Þ÷½ï{ÀB„!B„!B„"„!B„!B„!CÆ0‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUUUT@UUUUUUUUUUUUUUUUUUUUUUTð `a¨Usj+Ä+Ä|+Ä~±²|0Ô½5€Éj€Éj€g€Usa¨I>I>Œa€Œa€a¨s÷€a¨= jj7 € 57 s‚7 ú—€jI>˜–€a¨0Ô 5j= Us€,€½5€Œa€Œa€€,€s÷€g€a¨a¨0ÔUs0ÔI>±Y Žô$Éj€±€±€Œa€s÷€g€±€çïI—ÃÃÃ Ž ŽçïáÔ€ÕŸ€çï±€˜–€˜–€±€áÔ€ô$ÕŸ€çïô$çïçïÉj€ô$ Ž1-$øÃÃáÔ€çïô$Éj€ô$½5€¤Ë€±€˜–€˜–€¤Ë€¤Ë€¤Ë€±€s÷€s÷€˜–€¤Ë€çï Žô$áÔ€ô$çïô$˜–€g€g€Us$Ÿ 57 €77775€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ0$’I$’I$’JI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RÚçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUU@UUUUAUUUUTUUUUEUUð aú—‚7 €$Ÿ±²}€…‚±²+Ä}ú—ú—‚±²|0Ô= = I>Us0Ôjj$Ÿjçï€,€çïô$$ø=bô$ô$Y¤Ë€Éj€ô$Y ޽5€s÷€˜–€g€I>= 5±²}€…‚7 €…€jI>a¨a¨I>I>Usa¨s÷€Œa€ÕŸ€Éj€˜–€¤Ë€Œa€˜–€€,€0Ôj 5+Ä+Ä|= ¤Ë€ô$ ޱ€s÷€g€0Ô0Ôa¨¤Ë€áÔY½5€€,€½5€Œa€j+Ä~±²}s‚±²~7 € 5s÷€€,€áÔ€ÕŸ€ç€˜–€çï¤Ë€˜–€€,€¤Ë€$Ÿ$Ÿ0Ô$Ÿ+Ä| 5 57 ‚±²|jjUs½5€ô$çï±€˜–€¤Ë€˜–€7777€BUFRöbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ$@"""""""""""#333333333334DDDDDDffffffwwwwwwwwwwpŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUQTUUUUUUUUUUð `ô$YI—UÌbà ŽY1-$øçï=bYçïô$Ãô$ÕŸ€ÕŸ€˜–€½5€½5€Éj€±€¤Ë ŽÃYçïYô$çïçïÕŸ€±€¤Ë€s÷€I>0Ôj 5 5a¨= 0ÔI>a¨g€a¨g€Usg€= Usa¨s÷€€,€±Ya¨j$ŸI>€,€½5€Éj€½5€±€½5€ÕŸ€çïçïYô$€,€ 5+Ä|$Ÿ 5±²~±²|0Ô= Us¤Ë€½5€áÔ€±€½5€½51-$øn6bb1-I—UÌtPI—UÌI—I—Ãô$Éj€±€±€½5€çïÃ$øYçïÕŸ€Éj€Éj€Éj€Éj€çïô$ÕŸ€Éj€7777 BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀ@0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×Â2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUPUUUU@ð `½5€½5€±€˜–€s÷€a¨g€€,€€,€˜–€˜–€Éj=bô$Éj€áÔ€áÔ€çï½5€ÕŸ€Éj€±€˜–€a¨a¨g€˜–€˜–€½5€¤Ë€¤Ë€±€¤Ë€¤Ë€˜–€Œa€€,€Œa€˜–€Œa€±€˜–€±€Éj€½5€Éj€ÕŸ€ÕŸ€Éj€ÕŸ€ÕŸ€çïYÕŸ€Éj€Œa€˜–€áÔ€Éj€çïI—=b$øYçïçïYUÌ½Ž‚²²ÉÃ1- Ž ŽáÔ€Éj€¤Ë€s÷€€,€s÷€€,€˜–€±€çïÉj€ÕŸ€Éj€½5€áÔ€ÕŸ€áÔ€áÔ€ÕŸ€áÔ€±€±€¤Ë€Œa€0Ô 5 5±²+Ä|g€g€Œa€a¨s÷€g€€,€s÷€±€Éj€Œa€g€Us0Ô$Ÿ+Ä}ú—‚7 ‚±²~7 ‚±²}ú—€7777$BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÀX0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUPUUUUUUUUUUUUUUð ` 5˜–€áÔ€ÕŸ€½5€Œa€€,€jg€€,Y1-ô$ÕŸ€¤Ë€áÔ€çï½5€Éj€ÕŸ€Œa€€,€±€¤Ë€±€çï=b$øçïçïY$ø1-Yô$½5€áÔ€¤Ë€áÔ€˜–€±€½5€Éj€¤Ë€¤Ë€±€jjg€˜–€½5€˜–€Œa€a¨¤Ë€¤Ë€˜–€±€çïçï±€½5€áÔ€½5€˜–€½5€€,€0Ô$Ÿ±²}ú—€$Ÿ 5$Ÿ$Ÿ0Ôg€0ÔI>€,€Éj€Éj€¤Ë€±€±€g€Usa¨= a¨g€g€s÷€s÷€½5Ã$ø=bÃáÔ€ô$áÔ€çïÃb€…Yô$YçïáÔ€ô$±€Éj€˜–€˜–€Œa€s÷€¤Ë€Éj€ÕŸ€½5€˜–€s÷€˜–€s÷€7777$BUFR&bÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑÂUUUUUUUUUUU]kZÖµ­k{Þ÷½ï{Þ÷½ï{Þ÷½ïœç9Îsœç9Îsœç9Îs½ï{Þ÷½ï{Þ÷½ï{Þô!B„!„!cÆ0ŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUTUUUUUQUUUUTUUUUUUU@ð `Us½5 Žçïçï ŽÃ ŽYçïs÷€+Ä+Ä|j€,€Éj€áÔÃÃ1-à ŽÕŸ€ÕŸ€ô$ Ž ŽYÕŸ€Éj€s÷€s÷€0Ô±²}ú—s€Œa‚7 €0Ôs÷€¤Ë€Œa€˜–€¤Ë€¤Ë€Éj ŽÃçïô$çïÕŸ€±€±€¤Ë€€,€€,€I>$Ÿ+Ä| 5$ŸŒa€áÔ€áÔ€±€˜–€¤Ë€±€˜–€±€Éj€Éj€±€€,€€,€Œa€= I>jú—‚±²~7 €…€…€…€j$ŸI>Œa€˜–€= j= €,€˜–€¤Ë€¤Ë€Éj€±€½5€½5€ô$ÃYÉj€¤Ë€˜–€˜–€˜–€ÕŸY=b±€Us0Ôj+Ä}ú—ú—ú—€…‚7 ‚±²|77775€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠc¡*[çÆS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPU@TUUUUUUUUUUUUUUUUUUUUUUð aú—€$Ÿs÷€˜–€s÷€0Ô$Ÿj= s÷€ô$=b=b Ž1-YÉj€˜–€±€s÷€Us 5±²+Ä| 5$ŸI>€,€a¨+Ä}€…‚7 ‚7 ‚±²|$Ÿj$Ÿ0Ô$Ÿ±²| 5 5I>UsI>a¨¤Ë€½5€çï1-n6˜ï¥$$ø½5€±€çï ŽÕŸ€áÔ€½5€ÕŸ€áÔ€áÔ Žô$YYçï¤Ë€= g€€,€Œa€€,€g€s÷€€,€Œa€±€ÕŸ€Éj€±€±€ÕŸ€Éj€Éj€½5€¤Ë€˜–€±€˜–€€,€€,€Œa€¤Ë€¤Ë€ÕŸ€½5€½5€áÔ€ô$ÕŸ€Éj€Éj€ô$çï½5€±€Éj€Éj€˜–€Œa€s÷€±€±€g€$Ÿ0Ôs÷€s÷€= $Ÿ0Ô0ÔI>7777j€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ$0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUU@UUUUTUUUUUð `Œa€˜–€Œa€˜–€a¨Usg€UsI>0ÔI>= 5j$Ÿ0ÔI>s÷€˜–€˜–€s÷€s÷€€,€s÷€Œa€s÷€˜–€g€= Us= I>$Ÿj$Ÿ0Ô0Ô= Usg€s÷€s÷€s÷€€,€Œa€Œa€±€±€ÕŸ€ô$áÔ€ÕŸ€Éj€ÕŸ€çï1-1-b$øÃô$çïÃYY ŽYYYÉj€ÕŸ€ÕŸ€Éj€Éj€±€$ŸI>I>0Ô0Ô+Ä+Ä~7 ú—ú—ƒ+Ä|$Ÿg€Œa€s÷€˜–€Œa€Œa€Œa€€,€€,€€,€g€€,€Œa€s÷€I>I>$Ÿj7 €jjI>I>¤Ë€áÔ€Éj€½5€˜–€I>= a¨Œa€½5€ÕŸ€½5€Éj€ÕŸ€ÕŸ€Éj€7777j€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñ80I$’I$’I$’’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶í¶Û`‹pC!Lt%Kc\øFS¥mpC)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUQUUð `½5€¤Ë€±€˜–€Œa€€,€Œa€˜–€¤Ë€½5€±€½5€±€Œa€±€˜–€±€±€½5€±€½5€Œa€˜–€s÷€= 0Ô$Ÿj+Ä| 5+Ä| 50Ô0ÔI> 5±²~±²+Ä|= Us¤Ë€Éj€¤Ë€±€½5€˜–€¤Ë€˜–€s÷€¤Ë€Œa€a¨˜–€½5 ŽI— ŽYçïáÔ€ô$áÔ€çïà ŽYÕŸ€½5€±€±€±€€,€Œa€I>$Ÿ$Ÿ$Ÿs÷€€,€¤Ë€±€±€áÔ€Éj€±€áÔ€çïÉj Žô$çïáÔ€çïÉjYô$Éj€˜–€s÷€¤Ë€g€¤Ë€½5€˜–€±€€,€€,€˜–€€,€±€¤Ë€áÔ€ÕŸ€¤Ë€Œa€I>+Ä|$Ÿja¨g€€,€½5€çï$ø7777j€BUFRæbÿ« fÑ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑP0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÂ!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUTPUUUUAUUUUUUUUUUA@UUPTð aÃ=bà ŽYÕŸ€ô$ÕŸYÃ=bô$±€I>j+Ä|$Ÿjú—‚7 ‚±²| 5= €,€s÷€g€a¨s÷€UsUss÷€UsÉj€çï Ž¤Ë€€,€Us= j$Ÿ+Ä+Ä| 5$ŸjUs€,€UsI>0Ô= 0Ôa¨±€Œa€s÷€g€s÷€€,€a¨s÷€¤Ë€Œa€g€˜–€a¨I>g€€,€¤Ë€˜–€Œa€g€a¨Éj€ÕŸ€ÕŸ€Éj€s÷€g€g€I>$Ÿ±²+Ä|j$Ÿ+Ä}€…‚±²}€…€Œa€áÔ€áÔ€€,€0Ô= j$Ÿ 5 5 5±²+Ä}ú—ú—ú—‚7 €…ú—€Œa‚±²+Ä|$ŸUs½5€Éj€Us±²~±²+Ä| 5 57777j€BUFRæbÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ñd0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUQUUUUUUUUUUUUTUUUUP@UUUUð `= g€I>= I>= jj 5±²|±²|I>= 0Ôj 50Ô$Ÿ= 0Ô$Ÿ= UsáÔYô$±€a¨$Ÿ±²}ú—‚7 ‚±²|j$Ÿg€ 5= g€g€$Ÿ= Us€,€g€s÷€¤Ë€Œa€Œa€s÷€ 5$Ÿ7 ú—€O€Œas‚7 €…‚7 ‚±²~±²+Ä|jj= g€€,€g€€,€˜–€¤ËYYÕŸ€½5€€,€$Ÿ+Ä|Usg€0Ôg€Œa€¤Ë€Éj€ÕŸ€˜–€ô$ô$ÕŸ€±€áÔ€0Ô 5 5+Ä~±²|€…€Œassƒ+Ä| 50ÔjUsa¨a¨Œa€˜–€˜–YÕŸ€áÔ€½5€s÷€½5€±€Éj€s÷€7777j€BUFR6bÿ« fÑ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!âLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÑUUUUUUUUUUUUUUUUUUUUUUUUUTD»»»»»»»»»»»_{Þ÷½ï{Þ÷½ï{Þ÷€B„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œc!B„!@Š!¦:¥±®|#)Ò¶¸D2ÇBT¶5Ï„e:V×D2ÇBT¶5ÐŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@#`\I>$ø?x = †G$ø28ÆB@ 3á@€,€ô$“.“à ß4Ö )2àI>zÏ…·tôÖÄ´ ÓX™p/M`LK@ÃP1-ÄÄ´ ÓXw@@@zY·tŸ¼|(~ðw@3á@zçïèHd¡  0ÔLK@€,€ž±n6zÄ|(™p#`3á@OX€a¨n6õˆ™p,@ !‘À0Ôa¨=bd ÓX #`j$Ÿ0Ô0ÔzÄ¸Ø &% F0À˜–Ó.é¬ L¸™p)2à@@s÷€çï1†d L¸™p/M`F0À½5† Äé¬ 5„€I>˜–€ô$zk“.é¬ ÓX™p,@ LK@€,€·n6zÄ28 q° 5'¬@[€7777IBUFR¶bÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@&% ]I—1†¸Ø øPÐ)2àF0Às÷1-²c È ëO€ 5·ÏÞõˆ~ðýà@@€,Y“.zÄ28dp&% LK@˜–n61†d28€ð w@ž±Ûº·t¸ØÐ-ÆÀa¨¤Ë1-“.&\ øPýà@@X€@¤Ë1-1†Ÿ¼È q°ýà!‘ÀC#€·Ÿ >ÈÐ,@ ReÀ˜–1-“.Ä´?x q°&% 9ûÀg€· ŽÃPIðÝÐð -ÆÀs÷€çï“.Ÿ¼?x øPýàF0Àg€çïŸ c L¸™p,@ LK@Œab>¸Ø -ÆÀX€@¤Ë1-bZc ‰h ,@ LK@ŒaÃ1†d ™p-ÆÀF0À¤Ë€77770ÀBUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@(0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛnÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUPTUUUQUUUUUUUUUUUUð `áÔ€ÕŸ€ÕŸ€Éj€½5€±€½5€˜–€€,€±€¤Ë€€,€¤Ë€±€˜–€€,€¤Ë€¤Ë€Éj€½5€Éj€ô$YçïÕŸ€çïÕŸ€áÔ€Œa€Œa€Us= I>0Ô€,€˜–€ô$ÕŸ€Œa€€,€˜–€¤Ë€€,€s÷€a¨g€= $Ÿ0Ô$Ÿ+Ä~7 € 5+Ä~±²~7 ‚7 ú—ƒ+Ä|j= I>Usa¨a¨g€Œa€Éj€¤Ë€Œa€= = $Ÿ 5j+Ä|j= g€˜–YáÔ€¤Ë€½5€Œa€¤Ë€±€ç€±€€,€g€I>s÷€a¨0ÔI>0Ôj$ŸŒa€¤Ë€áÔ1-ô$Éj€˜–€˜–€¤Ë€½5Ã1-$øI—I—UÌI—1-Y±€g€Œa€I>7777½5BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@@0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTUUUUUUUUUUPTUUPUUU@Uð `s÷€ÕŸ€ÕŸ€áÔYçïáÔ€ô$ÕŸ€½5€Éj€áÔ ŽY±€¤Ë€˜–€¤Ë€a¨jj±²~7 €0ÔŒa€çï½5€½5€Éj€Œa€çïÕŸ ŽYYYÃ=b1-$øYáÔ€ô$ô$çïô$½5€Éj€áÔ=bUÌ$ø Žô$½5€±€±€˜–€˜–€s÷€0Ô0ÔI>I>g€= 0Ô7 €…ú—ƒ+Ä|= s÷€s÷€$Ÿ+Ä+Ä+Ä| 5ja¨áÔ€¤Ë€˜–€€,€= a¨Us= $Ÿ+Ä+Ä}ú—ƒ+Ä+Ä}ú—€…‚±²|+Ä| 5 5$Ÿg€Us= 0Ô€,€Œa€¤Ë€I> 5±²~7 ú—‚±²| 5= s÷€±€s÷€UsŒa€7777½5BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@T0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTUUUUUUUTPUUUUUUUUU@UUUð `UsŒa€¤Ë€¤Ë€˜–€˜–€0Ôs÷€Us0Ô 5€…‚7 ‚7 ƒ+Ä~7 ‚±²| 5g€ô$ Ža¨Œa€€,€0Ô$Ÿ€,€ŒaUÌYçï½5€áÔ€€,€a¨$Ÿ+Ä}ú—ú—ú—‚±²|0Ôs÷€€,€s÷€a¨s÷€I>s÷€a¨s÷€±€a¨Us0ÔI>0Ô 5+Ä|UsI>±²}€…ú—ƒ+Ä|$ŸUsUs0ÔUsçï¤Ë€€,€½5€Œa€˜–€±€Œa€Œa€çï¤Ë€¤Ë€€,€˜–YYÃçïáÔ€Éj€Éj€Éj€½5€˜–€g€˜–€˜–€¤Ë€€,€€,€s÷€g€Œa€0Ô7 ƒ+Ä}ú—ƒ+Ä~±²+Ä}ú—€…€jI> 5= çïs÷€€,€UsI>0Ô= j0Ô7777½5BUFR&bÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒBUU\ç:Öµ­kZÖµ­kZÖµ­k[Þ÷½ï{Þ÷½ï{Þ÷½óœç9Îsœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{ß{Þ÷½ï{Þ÷½ï{Þ÷½à‹[\ÈS RØ×>”é[\!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUUTUUEUUUUUUUUU@UUUUUAð `0Ô= j7 ‚±²}ú—‚±²+Ä|= €,€g€˜–€¤Ë€ÕŸ€Œa€€,€¤Ë€Œa€s÷€= $Ÿ±²+Ä~7 ‚7 €Œa€…‚7 ú—€Usg€UsI>j 5$Ÿ+Ä|0Ô= ±²~7 ƒ+Ä| 5ú—ƒ+Ä|+Ä+Ä~7 ‚±²| 5Œa€½5€çïÃÕŸ€Éj€±€g€˜–€€,€±€¤Ë€UsÕŸYÕŸ€ç€g€ 5ú—ƒ+Ä| 5g€Œa€¤Ë€Œa€Œa€±€ÕŸYÃY1- ŽÕŸ€áÔ€áÔ€Œa€€,ú—‚±²~±²}ú—€ja¨çïI—n6$ø¤Ë€ÕŸ€I>Usg€€,€€,€€,€ŒaU̘–€s÷€½5€±€Us0Ôj 5+Ä~±²| 577775BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€0I$’I$’I$¤’I$’I$’I¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶Ûm¶ÐŠ„©lkŸÊt­® …1Е-sáN•µÀ …1Е-sáN–¸2ÇBX×>”é[\ c¡*[çÂ2+k€C!Lt©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUEUUU@UUUTUUUUPUUUUð `= €,€a¨= Us$ŸUsa¨Œa€€,€UsI>j0Ô$Ÿ$Ÿ±²~7 s€Œas€…‚±²|$Ÿ$Ÿ0Ô= 0ÔI>Us= UsŒa€˜–€g€Œa€I>+Ä|+Ä}ú—‚7 ú—€…ú—ú—ƒ+Ä|0Ô0ÔUsa¨0ÔUsáÔ=bbçï$øI>±²+Ä~±²~7 €I>ÕŸÃI—Y¤Ë€I>€,€¤Ë€½5€½5€Œa€a¨j0Ô 5j€…‚7 ‚7 ú—€0Ô€,€áÔ€çï1-ÕŸ€¤Ë€s÷€I>½5€˜–€±ÃÕŸ€ô$ Ž¤Ë€= +Ä+Ä~7 ƒ+Ä~7 €0ÔUs0Ô= Us$Ÿ= Us€,€¤Ë€€,€˜–€˜–€Œa€Œa€g€7777>BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛnI$’I$’I$–Ûm¶ÐŠˆe1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B™ SÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUPQUUPQUUPUUUU@Uð `Us±€¤Ë€¤Ë€Œa€Œa=bUÌçïçïÕŸ€Éj€áÔ€±€s÷€Œa€Éj€½5€€,€Œa€s÷€g€a¨I>a¨g€j0ÔUs€,$øÃb1-Ãô$ÕŸ€±€Œa€a¨s÷€Usa¨0Ô0Ô= 5±²}ss‚±²+Ä|$Ÿ 5+Ä|$Ÿ 5 5j0ÔI>0Ô= 5 5+Ä~±²}€…ú—€…ú—‚7 € 5j$Ÿ 5$Ÿ+Ä|a¨= = Us= a¨I>g€Us= 5±²}ú—ú—ú—ƒ+Ä+Ä|= s÷€€,€Œa€a¨a¨UsI>= g€Œa€UsI>0Ô$Ÿj+Ä}€…ú—‚±²|UsÃÕŸ€˜–€g€Us7777>BUFR¶bÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€00 $’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÛmÛ`ŠçÂ2+k€" c¡.|#)Ò¶¸!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ ]YÏÞÝÐŒ0!‘À9ûÀ$Ÿ˜–ÃbZ$øÆ F0À½5ÏÞ28 ë˨w@B@3á@g€’|$ø† ¸Ø 'ÀB@„€0ÔI>a¨† ™pC#€Œa€çïzkôÖd“à 'À#`dµAÃzÄ%ªÄ´ ÓXð ReÀ­óAUÌbZ28È~ð&% iI äáÁÜJIoš ‰hÖ &% OX€ªæh‚zÄW0 L¸Ö )2àUsž±Ãc ÆŒ0*¹€ReÀ­óAI—ÏÞôÖ?x ÓXð C#€zÃ1†28?x~ðw@,@ dµ@Ï…·tŸ¼?xŒ0!‘À/M`F0À= Yô$a¨ @¡ dµ@½5·t²Ÿ¼ @¡ B@„€j7777BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€H0$’I$’I$’II$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚáÈS RØ×>”é[\ c¡*[çÂ2+k€" c¡*[çÂ2+k€C!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUPQUUUUUUUQTð `= Us¤Ë€¤Ë€Éj Ž¤Ë€a¨Usa¨0Ô= a¨€,€s÷€Usg€0Ôa¨I>±²}ú—sú—€…ú—€= €,€½5€˜–€s÷€Uss÷€a¨g€¤Ë€±€¤Ë€a¨$Ÿ 5±²~7 ‚7 ‚±²}€…€…ú—‚7 €jI>0Ô= ±²|jjj0ÔŒa€ÕŸ€±€g€0Ôú—‚7 ƒ+Ä|0Ô= 0Ô= s÷€çïUÌtPn61-Ãç€¤ËÃÃô$ÕŸ€Œa€€,€a¨j$Ÿ+Ä|€…‚7 ú—‚7 ƒ+Ä|= 0Ô$Ÿ7 €$Ÿ+Ä+Ä|0Ô$Ÿ$Ÿ$Ÿj 5+Ä~±²}ú—ú—€…ú—ú—€…ú—‚±²+Ä|j+Ä|$Ÿ$Ÿj7777>BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€\0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%KkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðU@UUUUUUUUUUPUUT@UUUUPUUUUð `j$Ÿ0Ôj7 ƒ+Ä~±²+Ä|= ±²~±²|€,€Œa€UsUsI>= 0ÔUs˜–€g€a¨¤Ë€ô$$ø1-Y1-ñ€Œa€€,€±€ÕŸ€s÷€a¨¤Ë1- ŽáÔ€g€€,€±€g€Us€,€Œa€s÷€s÷€¤Ë€g€a¨a¨I>ú—‚±²~±²~7 ‚7 ú—ƒ+Ä| 5 5$Ÿs÷€g€Éj€I>Us= j+Ä|jú—ú—‚±²}ú—ú—€0Ôg€˜–€= Us0ÔUs= a¨s÷€Œa€g€¤Ë€½5€€,€¤Ë€s÷€€,€I>7 ‚±²+Ä|I>s÷€ô$I—±€a¨= = 0ÔjI>s÷€˜–UÌ=bUÌ=b=b=b7777>BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀ0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆe1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTUUUUUUUUUUUEUUUUUUUUUUUUUUUUPUýàa1- ŽÕŸƒ|ú>ƒ|0Ôg€՟€s÷€s÷€UsI>= = s÷€j[€ÕŸ1-ÃYÉj€Éj€ô$$ø ŽÉj€ÕŸ€ÛºÛºçïÕŸ€¤Ë€Œa€s÷€g€[€0Ô$ŸŒa€Œa€Éj€½5€ÛºÛº˜–€s÷€I>= $Ÿj$Ÿ¥}|0Ô[€$Ÿ0Ôj 5= jjj0Ô€,€¤Ë€½5€½5€¤Ë€ÕŸÃ ޽5€g€s÷€s÷€¤Ë€çïUÌ1- ŽÛº±€[€g€Us€,€ô$Y±€0Ô€,€Œa€Ûº¤ËI—1-YY½5€Œa€Éj€ÕŸ€Ûº˜–€I>0Ô= [€0Ôg€¤Ë€Œa€€,€Éj€UsUs 5 5¥}~¥}|jI>g€ۺ7777>BUFRöbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀ@""""""""""""333333333333DDDDDDDDDDDDUUUUUUWwwpŠ•-sáN•µÀÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶B2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUUUUUUTUU@UU@UEUUUUQUð `±€Œa€a¨= $Ÿ= 0Ô= a¨Us0Ô0Ô 5±²}€…€…ú—€…s‚7 €= I>g€0Ô$Ÿ0Ô$Ÿ= = a¨Œa€çïáÔ€…€…€…tPtP€ô$ÕŸ€¤Ë€¤Ë€±€½5€½5€¤Ë€¤Ë€UsUs0Ô= $Ÿ= s÷€g€a¨€,€g€I>+Ä~7 ‚±²|$Ÿ$Ÿ0Ôa¨s÷€€,€¤Ë€a¨˜–€$Ÿ 5ú—‚7 ú—ú—ƒ+Ä|$Ÿ$Ÿ$ŸI>= ÕŸ€Éj€g€UsI>±²}€…‚7 ‚7 ‚±²~7 € 5j 5$Ÿ+Ä|$Ÿ 5$ŸUss÷€Œa€g€0Ô= $Ÿ$Ÿ= a¨˜– Ž Ž ŽŒa€Us= +Ä|$Ÿ= I>= = 7777€ŒBUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀ40 $’I$’I$’’I$’I$’I&Ûm¶Ûm¶ÛmÉ$’I$’I$’Ûm¶Ûm¶Ûm»m¶Û`‹k€" c¡*c\øFS¥mpC!Lt%LkŸÊt­®ˆd)Ž„©sáN•µÀ …1Е1®|#)Ò¶¸!¦:¦5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTQUUPUUUUUUUUUUUUUQDUUUUUUUð `a¨0Ô±²}ú—ú—s‚7 ‚±²|$Ÿj 5+Ä|j 5$Ÿ0Ô0Ô$Ÿ0Ô$Ÿj 5j±²+Ä~±²+Ä| 50ÔUsg€= g€a¨±€±€Éj€Éj€±€Éj€ÕŸ€ô$ Ž$øYYÃ1-Ys÷€$Ÿ¤Ë€Œa€Usa¨áÔYÕŸ€½5€˜–€¤Ë Ž˜–€I>€,€UsUs= 5$Ÿj= ±²|0Ô= g€g€a¨ 5j0Ô$ŸUs€,€€,€j+Ä|+Ä+Ä+Ä| 5= ±²| 5±²|ja¨¤Ë€˜–€g€g€a¨Éj€áÔ Žb1- Ž¤Ë€¤Ë€˜–€UsUs0Ô= ¤Ë€áÔ Ž$ø=b=báÔ€±€7777>BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀL0$’I$’I$’JI$’I$’I$›m¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶Ûm¶àŠÆ¹ðŒ§JÚà†B˜èJ˜×>”é[\ÈS SçÂ2+k€" c¡*c\øFS¥mpC!Lt%LkŸÊt­®ˆd)Ž„©sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUDUUUUUUUUUUQUUUTUQUUUð `Œa€a¨Usg€½5b=btP€ÕŸ€Éj€½5€a¨ 5+Ä|0Ô+Ä~±²|ÕŸ€ô$1-ô$½5€Éj€Œa€s÷€ÕŸ$ø¥$n6ÃÃ$ø˜–€€,€Us= jj 5 5±€Éj€¤Ë€Éj€Œa€Usjj0ÔUss÷€˜–€¤Ë€áÔ€ô$áÔbçïŒa€Éj€0Ô±²|ja¨˜–€½5€½5€Œa€˜–€Œa€˜–€½5€ÉjYY¤Ë€a¨+Ä}ú—ú—€Œa€Œaú—ƒ+Ä}ú—‚7 ‚±²~7 ú—ú—€…‚7 ‚±²~±²+Ä|= 0Ô0Ôjj 5+Ä}ú—‚7 ‚7 ‚±²~±²+Ä|j$Ÿj+Ä|= I>0Ô= = s÷€Œa€Éj€½5=b$øÃçï7777>BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀd0’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠ …1Е1®|e:V×D2ÇBTƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUEUUUUUUUUUUUUUð `I>g€I>a¨Œa1-I—=bçï½51-ÃI—$øtPÕøtP=bYg€Usg€UsI>= a¨s÷€˜–YY±€½5€I>0Ô= 50Ô$ŸI>UsUsa¨0ÔUs½5€½5€˜–€s÷€˜–€áÔY1-ÕŸ€çïŒa€I>I>j0ÔI>Œa€áÔ€Éj$ø=bô$¤Ë€¤Ë€€,€a¨0Ôj+Ä|UsY½5€½5€½5€a¨g€s÷€€,€Œa€s÷€±€ÕŸUÌ$øYŒa€Éj1-=b ŽYÉj€Éj€çïáÔ€áÔ€¤Ë€áÔ€½5€˜–€¤Ë€Œa€˜–€˜–€çï=bâ-‚%Q²½Ž½Ž½ŽŒºbY$ø=b=b˜ï½ŽYUs7777>BUFRöbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÂUUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½÷½ï{Þ÷½ï{Þ÷½ï{ÞB„!B„!B„B„!B„!B„! cÆ1ŒcÆ1ŒcÆ0ŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡*[çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð ]bŸ ?x L¸³ðLK@äáÁŒºƒ  eÔHýàI>^šÀ¤Ë€’|²Ä´~ðÐ 9ûÀI>’|a¨$øIð øP)2àX€AYzkV~¬ü –¨¦° 'ÀO€ 5a¨a¨† ¡ B@„€I>I>1†d L¸ 2Z „€s÷€ÃPÏÞIð€ @= ’|Ÿ Ÿ¼|( øPB@O€I>Ï…ôÖ>€ 5\À*¹€s÷€za¨a¨Ið“à @O€a¨1-ÏÞÄ´?xO€„€I>zŸ >È:= s÷ ŽÄ28Ÿ¼Æ5gà’|$øÏÞ‡Rdp –¨™p $Ÿ0ÔªæUÌ>È~ðB@3á@= 7777€ŒBUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò0I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶Û’I$’I$’Im¶Ûm¶ÐŠ …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RÜøFS¥mpd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@UUUUPTPUUUUUUUUUUEð `±²~7 ƒ+Ä|Us¤Ë€g€a¨g€a¨= I>= I>I>Us= g€Us$Ÿ$Ÿ+Ä~±²~7 ‚7 ‚7 ‚7 ƒ+Ä|j+Ä+Ä~7 ‚±²~7 ú—‚±²~±²~7 ‚7 ‚7 € 5j 5$Ÿ±²|+Ä+Ä~±²~7 ‚7 ú—s€…€…ú—€…‚7 ‚±²~7 €j 5j+Ä|I>7 €I>ô$$ø=b ޽5€$Ÿ$Ÿ7 ƒ+Ä~7 ‚7 ‚±²| 5a¨a¨Œa€a¨ 5= g€a¨s÷€ÕŸ Ž$ø=bYŒa€Usa¨s÷€€,€g€0ÔUs0Ôj$Ÿ+Ä}ú—‚±²~±²~7 €= ½5€áÔ€Œa€a¨= j$Ÿ+Ä| 5$Ÿ7777B@BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò(0I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶Û’I$’I$’I%¶Ûm¶Ûm¶ÛvÛ`‹Êt­® …1Е-Ž|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡*[çÂ2+k€C!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `j 5 5I>g€UsI>$ŸI>˜–€áÔ ŽY½5€I>g€0Ôj$Ÿ$Ÿ$Ÿ$Ÿa¨€,€Œa€Éj€¤Ë€Éj=b=bI—tP˜ï±YUÌà Žô$±€Œa€Œa€Us¤Ë€±€g€UsI>= ¤Ë€€,€s÷€Œa€a¨a¨€,€±€áÔ€s÷€I>$Ÿ$Ÿ0ÔI>Uss÷€€,€UsUsŒa€Éj€ô$g€áÔ=bYáÔ€±€±€¤Ë€¤Ë€€,‚±²| 5+Ä+Ä| 5 5 5$Ÿ0Ô= s÷€a¨s÷€0ÔUsj$Ÿa¨ÕŸ1-ô$½5€Œa€Œa€˜–€ÕŸ€Œa€±Ø–€s÷€Éj$ø1-n6n6€…$øô$Y Žn67777B@BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@0I$’I$’I$”’I$’I$’I6Ûm¶Ûm¶ÛnI$’I$’I$–Ûm¶Ûm¶ÐŠt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUEUUUUUUUUUUUUUUUUUUUUð a˜ïîb½Ž€Éj€Œa€˜–€s÷€s÷€˜–€s÷€€,€çïô$±Y‚ çÉØïUÌ=b ŽçïYtP‚ ç¥$€áÔ€Éj€˜–€= g€˜–€Éj€Œa€Œa€s÷€0Ô±€I>$Ÿs÷€g‚7 €˜–€çïYÉj€½5€Usg€$Ÿ= 0Ôa¨çïÉj€¤Ë€çï1-1-Éj1-I—Éj€0Ôj 5I>½5€ô$ÕŸ€áÔYÃY½5€¤Ë€ÕŸ€¤Ë€±€ÕŸ€çï1-1-UÌ ŽÃÕŸ€ô$áÔ€Éj€ô$ô$Éj€ç€±€s÷€s÷€¤Ë€ÕŸ€˜–€¤Ë€Éj$øYçïŒa€g€g€$Ÿ 5+Ä|+Ä| 5$ŸUsI>= = = Usa¨Œa€˜–€áÔ€7777B@BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒT0$’I$’I$’JI$’I$’I$Ûm¶Ûm¶Ûm¹$’I$’I$’[m¶Ûm¶Ûm·m¶Û`‹JÚàÈS RØ×>”é[\ c¡*[øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUU@UUUUUUUUUUQEð `½5YÕŸ€ô$s÷€g€€,€Éj€Éj€˜–€çïÕŸ€¤Ë€I>a¨0ÔI>UsI>0Ô= jg€s÷€±€ô$ô$çï½5€˜–€˜–€ÕŸ€áÔY½5€¤Ë€¤Ë€Us0Ô= Us€,€€,€€,€Œa€Œa€s÷€I>$ŸUs0Ô= I>Œa€ÕŸ€¤Ë€Œa€¤Ë€¤Ë€±€˜–€s÷€€,€I>= g€Us1-˜ï1-$øY½5ú—‚±²+Ä|$Ÿ€,€˜–€±€s÷€g€a¨g€s÷€€,€˜–€s÷€Usa¨˜–€áÔY= g€$ŸUsI>UsUs˜–€çïçïÉj€¤Ë€g€Us= = UsI>= 0Ô$ŸI>= $Ÿ+Ä|I>= ú—€+Ä| 5$Ÿ7777B@BUFR&bÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒUUUUUUUUUUU]kZÖµ­kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ç9Îsœç9Îsœç9Îs½ï{Þ÷½ï{Þ÷½ï{Þ€„!B„!B„!B ж5Ï„e:V׆B˜èJ–ƹðŒ§JÚà c¡*[çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUE@UTETUUUUPPEUUUUUUUUð ` 5j 5 5= Us¤Ë€±€$Ÿ±²| 5±²}€…‚7 s‚±²| 5+Ä+Ä}ú—ƒ+Ä~±²~7 € 5$Ÿ$Ÿ= g€ 57 €$Ÿ$ŸŒa‚7 ‚7 €$Ÿ= $Ÿ0Ôjj+Ä~7 ƒ+Ä| 5 5j+Ä|j 5Éj€±€Ussƒ+Ä~7 ƒ+Ä|UsÉj€¤Ë€Œa€a¨Us˜–€Éj€Éj€±€±€½5€= €,I—Éj€½5€¤Ë€Us€…s‚7 ‚7 €0Ô$Ÿj$Ÿ+Ä+Ä|7 €jUsg€±€a¨ÉjṲˀÉj ŽçïáÔ€ÕŸ€¤Ë€ÕŸ€áÔUÌ$øŒa€˜–€±€˜–€Us±€ŒaY±€I>s÷€€,€Œa€g€g€€,€77775BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@ 0’I$’I$’I)$’I$’I$’m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡*[çÂ2+k€C!Lt%LkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUTU@UQUTUUUUUUUUUð `g€I>€,€ÉjYçï½5€çïŒa€Œa€ô$ÉjÃçïŒa€½5$øYb¤Ë€±€¤Ë€a¨a¨s÷€Éj€¤Ë€˜–€¤Ë€Œa€$ŸI>= 0Ô$Ÿ$Ÿ$Ÿ 5 5a¨g€UsI>s÷€0Ô$Ÿ$Ÿ$Ÿ 5+Ä}ú—ú—‚7 ‚±²+Ä|±²~7 ‚±²~±²+Ä+Ä| 5$Ÿ$Ÿ= 57 ú—‚7 ‚±²|jj 5$Ÿ$Ÿ$Ÿ$Ÿ$Ÿ+Ä| 5 5j0Ô= $Ÿ= 5+Ä|jjI>Œa€Éj€±€˜–€€,€˜–€¤Ë€˜–€±€˜–€I>a¨s÷€€,€UsUs0Ô 50Ôj0Ô0ÔUsŒa€s÷€€,€s÷€= UsUsg€7777ÔBUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@ 0I$’I$’I$¤’I$’I$’I¶Ûm¶Ûm¶ÛrI$’I$’I$¶Ûm¶Ûm¶ÛnÛ`‹Êt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `I>I>= $Ÿ$Ÿj$Ÿ0Ô0Ô= jI>˜–€áÔ€çïÉj€áÔ€ô$áÔYçïYY Žçïçï=b$øÉj€±€Œa€UsI>g€՟Ã$ø ŽáÔYÕŸ€áÔ€ÕŸ€½5€ô$ô$çï€,€±€Œa€¤Ë€¤Ë€ÕŸ€˜–€I>$Ÿ0Ô= a¨s÷€Œa€g€g€UsUsI>$ŸUs= = 0ÔUs€,€±€¤Ë€˜–€I>a¨0Ô0Ô0Ôs÷€a¨$ŸUs= = $Ÿ$Ÿ€,€g€ 50Ôa¨I>a¨€,€$Ÿj 5 50Ôj= Us˜–€a¨g€UsUsg€UsUsUs= g€˜–€a¨g€$Ÿ 5j7 ‚±²+Ä|$Ÿ7777ÔBUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@80 $’I$’I$’’I$’I$’I&Ûm¶Ûm¶ÛmÉ$’I$’I$’Ûm¶Ûm¶ÐŠc¡*[çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUEUUUUUUUð `= g€I>jjj$Ÿ$Ÿ 5I>$Ÿj 5j˜–€Œa€ÕŸ€a¨$Ÿ 5$Ÿ0Ô˜–€¤Ë€½5€˜–€a¨g€€,€Usg€s÷€s÷€s÷€±€çïÃÉj€çï¤Ë€I>a¨s÷€¤Ë€½5Y Ž ޽5€a¨$Ÿ$Ÿ 5$Ÿ$Ÿ0Ô$Ÿ 50ÔUs 5+Ä+Ä~7 ƒ+Ä+Ä|j0Ô0Ô= = 0Ôjj0Ô 5j+Ä|±²~7 ‚±²~7 ‚7 ú—‚7 €j0ÔI>g€½5€¤Ë€ÕŸ€€,€Usg€= I>0Ô 50Ôg€՟€áÔYa¨$Ÿ±²}€…ú—‚7 ‚7 €= Us= I>I>I>0Ôa¨g€Us7777ÔBUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@L0’I$’I$’II$’I$’I$Ûm¶Ûm¶Ûm¹$’I$’I$’[m¶Ûm¶Ûm·m¶Û`‹:V׆B˜èJ–ƹðŒ§JÚàÈS c\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUU@UUUUUUUEAUUUUTUUUUTAð `I>0Ô= j±²~7 ‚7 ‚7 ‚7 € 50Ôg€g€Usa¨a¨a¨I>UsUs€,€I>0Ô= $Ÿ€,€j±²~7 ƒ+Ä|$ŸUs€,€€,€€,€0Ô= I>a¨a¨a¨0Ô$Ÿ= j 57 €…ú—‚7 ƒ+Ä|0Ô$Ÿ= = = I>= 0Ôj0ÔI>= I>$Ÿ$Ÿj+Ä| 5jj7 ú—€jI>€,€˜–€UsI>UsI>a¨I>g€€,€Œa€a¨ÕŸ€Éj€¤Ë€I>+Ä~±²}€…ú—‚7 € 5a¨˜–€I>I>jI>$Ÿ$Ÿj0Ô 5 5jjUsg€g€= +Ä}s‚7 ƒ+Ä~±²|+Ä~±²| 57777ÔBUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@d0’I$’I$’II$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’Im¶Ûm¶Ûm¶Ðж5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡*[çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUEUUUUUUUUUUUUUUTUUUUUUUUUUð `I>j˜–€Usa¨s÷€±€$Ÿ 5 5j7 €$Ÿ7 ss‚7 ‚7 ƒ+Ä|Us7 €I>0Ôg€s÷€Œa€˜–€I>0Ôçï$øI—tPUÌÕŸ€= = I>= s÷€½5€Éj€€,€Uss÷€s÷€Us$Ÿ0Ô˜–€áÔ€¤ËYÉjÃŒa€¤Ë€±€g€= j0Ô= 0Ô= = 0Ô$Ÿ= j$Ÿg€½5€ô$½5€çïçïYs÷€0Ô7 ‚7 ‚7 € 50Ôg€= 0Ô 50Ô$Ÿ$Ÿ$Ÿ$Ÿ0Ô 5I>ÃáÔ€çï¤Ë€ 50Ôa¨±€ÕŸ€Œa€Éj€˜–€g€˜–€$ŸUsa¨I>0Ô0Ô€,$øI— Ž7777ÔBUFR&bÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒBUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷½ï{Þ÷¼„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œd!B„!@Š …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUTUPPUUUUUUUUUUUUð `a¨$ŸI>s÷€g€a¨€,€= $ŸI>j0ÔI>0ÔUs= a¨g€՟Ãn6UÌb$øÃý5€¤Ë€ÕŸ€½5€I>I>= 5+Ä| 5 5±²~±²}ú—‚7 ú—‚7 ‚7 ‚±²~±²}ú—ú—ƒ+Ä|j 5±²}ú—‚7 ‚±²}ú—ƒ+Ä+Ä+Ä+Ä|+Ä|0Ô0ÔI>Éj€0Ô7 ú—‚±²~±²+Ä|±²|s÷€a¨€,€0Ô$Ÿa¨= I> 5 5 5UsI>½5€Œa€s÷€= j$ŸI>$ŸUsUs= jg€j0Ô0Ô$Ÿ$Ÿ$Ÿ0Ô0ÔŒa€a¨g€0Ô$Ÿ0Ôa¨UsUs€,€Éj€˜–€¤Ë€áÔ€ô$77775BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€0I$’I$’I$¤’I$’I$’I¶Ûm¶Ûm¶ÛrI$’I$’I$¶Ûm¶Ûm¶ÛvÛ`‹Êt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RÚçÂ2+k€C!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUPUTUUUTUUUUUð a$ø$ø ޱ€€,€g€g€UsI>$Ÿ±²~±²|$Ÿa¨¤Ë€ÕŸ€ÕŸ€áÔ€ô$€,€s÷€Œa€˜–€€,€a¨= = 0ÔI>0Ô$Ÿjjj0ÔI>$Ÿ0Ô= a¨g€a¨I>Usg€g€±€ÕŸY1- ŽYÃô$áÔ€s÷€= = a¨a¨I>+Ä+Ä~7 € 5±²~±²|a¨Œa€˜–€¤Ë€€,€g€= jjú—‚7 ‚7 ƒ+Ä~±²|$Ÿ¤Ë€g€0Ôjj 5$ŸI> 5¤Ë€$Ÿ±€Œa€ 5±²~7 ‚±²~7 ‚±²+Ä|jUsa¨g€0Ô 5jjUsI>= = 0Ô 5 Žs÷€½5€= $Ÿ 5jjI>7777ŸBUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€,0I$’I$’I$”’I$’I$’I6Ûm¶Ûm¶ÛnI$’I$’I$–Ûm¶Ûm¶ÐŠt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUQUUUUUTUUUUTUUAU@UUUð `UsUs0Ô 5j$Ÿ 5 5s÷€g€Œa€I>€,€çï±€¤Ë€= 5= Éj€g€a¨= I>$Ÿ$Ÿ= 0Ô= $Ÿ€,€I>I>j= ¤Ë€a¨Us= +Ä|Uss÷€g€I>UsI> 5$Ÿ= 0Ôg€s÷€a¨€, ŽÉj€½5€I>0Ôjj 5±²| 5j 5$ŸjI>j= 0Ô= €,€I>js÷€g€s÷€0Ô+Ä+Ä~7 €$Ÿ 5$Ÿ 5= 5 5 5+Ä+Ä|a¨s÷YŒa€0Ô±²+Ä~7 ‚±²|Œa‚±²|= = j 50Ô0Ô$Ÿs÷€0ÔUsa¨jI>7777ŸBUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€@0$’I$’I$’JI$’I$’I$›m¶Ûm¶Ûm¹$’I$’I$’[m¶Ûm¶Ûm·m¶Û`‹JÚàÈS RØ×>”é[\ c¡*[çÂ2+k€C!Lt%LkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUTUð `s÷€½5€Usj7 €+Ä| 5j€,€g€j= $Ÿ= $Ÿ0Ô= = Usg€±€˜–€Œa€Œa€€,€$Ÿ0ÔjUss÷€˜–€Usa¨= j 5$Ÿj 5$Ÿj 5$Ÿa¨s÷€0Ô 5$Ÿ= = 0Ô$Ÿ$Ÿ0ÔjI> 50Ôs÷€€,€¤Ë€¤Ë€˜–n6n6˜ïUÌô$ÕŸ€½5€çïÉj€áÔ$ø$ø$øY±€˜–€a¨g€I>€,€UsUs±€ô$€…n6ô$Éj€±€ÕŸ€±€±€Éj€˜–€I>I>a¨= €,€¤Ë€Œa€˜–€±€Œa€Œa€Éj€±€I>I>I>+Ä~±²~7 ‚±²~7 €j 5j0Ô7777ŸBUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€X0’I$’I$’II$’I$’I$›m¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶Ûm¶àж5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUUUUUUUUUð `j$Ÿ 5 5jjjI>+Ä+Ä~±²+Ä+Ä+Ä+Ä~7 €…‚7 ‚7 €…‚7 ‚±²~7 ‚7 ‚7 ‚7 ú—‚±²~7 € 5= Usj±²~±²|= a¨Œa€s÷€0Ô= I>0Ô 5$Ÿ$Ÿ$Ÿ$Ÿ0Ôj0ÔI>Us0Ô0Ô$Ÿa¨s÷€Œa€˜–€¤Ë€¤Ë€€,€I>a¨= = $Ÿ0Ô0Ô0Ô0Ô$Ÿ$Ÿ= g€a¨I>Usg€Us€,€€,€g€s÷€Us€,€UsI>= 0Ôj0ÔUs0Ô$Ÿ 5+Ä|0Ô±²~7 ‚7 ‚7 ‚±²|$Ÿ$Ÿ0ÔUsUsa¨Us= j$Ÿjj+Ä+Ä|j 5 5 57777ŸBUFR&bÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò‚UUUUUUUUUUUUUUU]ï{Þ÷½ï{Þ÷½ï{ÞùÎsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½B„!B„!B„!„!B„ Š!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUUUUE@UUUPU@EDUUUð ` 5+Ä|ja¨€,€Œa€a¨$Ÿ$ŸI>0Ô= $Ÿ= $Ÿj0ÔI>I>Us= 0Ô+Ä+Ä|= a¨s÷ƒ+Ä|j±²~7 ‚±²+Ä~±²~±²|7 ‚7 ‚±²+Ä| 5j±²~7 ƒ+Ä+Ä~7 ‚±²}€…€Œaú—‚7 ‚7 ‚7 ƒ+Ä}ú—‚7 ú—ú—€I>g€0Ô= ú—€…€…sú—€j= Us0Ôs÷€jUsŒa€g€= ±²+Ä|j= €,€Us+Ä~±²~±²| 5±²|jI>j+Ä|7 ‚±²+Ä|$Ÿ0Ô0ÔI>€,€€,€Us0Ô$Ÿú—€ss‚7 €jI>a¨s÷€g€UsŒa€77775BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀ 0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTUUUUPUUUUQUUUUUUUPUUUUUUð `Uss÷€áÔ€±€çïÕŸ€Us= Us 5 5ú—‚7 ú—s€…ƒ+Ä|j= UsUs$Ÿ$Ÿ0Ô 5= 0Ôs÷€a¨Us±€Éj€Éj€½5€¤Ë€Usú—€Œa‚7 €= €,€˜–€€,€a¨g€Us€,€= g€a¨a¨= j0Ô 5I>I>= 5 5+Ä|jjI>g€= = s÷€s÷€I>s÷€UsUs½5€½5€½5€ô$Y¤Ë€= j$ŸI>$ŸUs= I>$Ÿ€,€j+Ä| 5 5 5+Ä+Ä|$Ÿ0ÔUsg€±€Us= +Ä}€…€…‚±²| 5j= = 0Ô 50ÔI>0Ô$ŸUsa¨Œa€a¨±€Éj€7777ÔBUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀ 0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUTUUUUUUUUUUUUUUQUð `˜–€Éj€˜–€= j0ÔI>$Ÿ0Ô0ÔUsg€€,€g€s÷€UsŒa€a¨g€˜–€0ÔI>€,€áÔ€±€¤Ë€˜–€a¨= I>a¨= I>g€Us 5$Ÿ= Us= a¨ 5 5= áÔ€½5€Éj€Éj€˜–€Œa€= = = s÷€I>0Ô0Ôj0ÔUsgƒ+Ä|a¨0Ôa¨= ±€g€Usa¨€,€±€áÔ€½5€Éj€¤Ë€Œa€s÷€a¨s÷€±€˜–€I>a¨$Ÿ$Ÿa¨I>= s÷€s÷€a¨Œa€Éj€g€ô$Ãô$½5€¤Ë€g€Œa€a¨Œa€s÷€= I>0ÔUss÷€I>Us¤Ë€I>a¨$Ÿg€0Ôj$Ÿ+Ä|j˜–€˜–€±€Œa€7777ÔBUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀ80$’I$’I$’JI$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUUUUUTUUUUUUTQTUPUUð `s÷€˜–€ÕŸ€€,€$ŸUs+Ä~7 ‚7 ‚±²|7 €= = UsUsI>I>= I>€,€s÷€€,€I>I>s÷€$Ÿ= a¨$Ÿ±€Œa€€,€a¨Œa€Us$Ÿ= $Ÿ= 5$Ÿj= = g€Œa€±€€,€UsI>0ÔI>a¨I>= = = = g€I>j+Ä~7 €jI>a¨g€a¨Us= UsUsI>I>g€Œa€a¨I>0Ôs÷€˜–€€,€a¨a¨I>Uss÷€g€= UsUs0Ôj±²|7 € 5+Ä|j$Ÿ 5jj 5ú—ƒ+Ä}ú—€ 5 5$Ÿa¨a¨= I>= 5Us= 7777ÔBUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀL0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUAUUUUU@TUUUUUUTUUUQUUUUUð `a¨I>¤Ë€I>Usa¨a¨˜–€Œa€€,€I>jj+Ä+Ä|0ÔUsI>s÷€I>Us= jj= g€a¨0Ô0Ô˜–€g€a¨a¨$ŸUs= j7 ú—‚7 ‚7 €…‚7 ‚7 ƒ+Ä~±²| 5jj+Ä|$Ÿs÷€g€Us0Ô$Ÿ$Ÿj+Ä|$Ÿa¨s÷€a¨a¨g€Us 50Ô 50Ô= $Ÿjj$ŸI>±€½5€Œa€¤Ë€0Ô+Ä+Ä|0Ô0ÔI>I>= $Ÿj 5jj0Ô= $Ÿ 5 5 5+Ä|7 € 5+Ä|$Ÿ$ŸI>$Ÿg€UsUs0Ôjjj$Ÿ$Ÿ0Ô= $ŸI>I>a¨0Ô 57777ÔBUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀd0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUTUUUUUUUUUUUUUUPEUQPUUUUUUUð `jj7 €$Ÿa¨g€UsI>$Ÿj0Ô$Ÿ$Ÿ$Ÿj±²|j$Ÿ$Ÿ0Ô0Ôj 5= UsI>Us$Ÿ0ÔI>I>$Ÿ$Ÿ0Ô= = I>0Ô$ŸUs0Ô0Ԥˀ¤Ë€Éj€Éj€€,€s÷€Œa€UsI>s÷€= UsUs= j0Ôj 5j$Ÿj 50Ô$Ÿ0ÔjUsçï€,€I> 5+Ä~7 € 5ú—€$Ÿ 5 5j= ±²|j$Ÿ+Ä+Ä|UsŒa€¤Ë€áÔ€ÕŸ€ÕŸ€Éj€¤Ë€˜–€s÷€¤Ë€ÕŸ€¤Ë€€,€= j+Ä|j+Ä|= jŒa1-g€= $Ÿú—€ 50Ô$ŸçïUÌY7777ÔBUFR&bÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÂUUUUUUUUUUUUUUUUUUUUUU^÷½ï{Þ÷½ï{ï{Þ÷½ï{Þ÷½ï{Þ÷¼„!B„!B„!B!B„!B„!B„1ŒcÆ1ŒcÆ0Š„©lkáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUEUTQUUUUUUUUUUUUUUUUUUUUUETýàa1-¤Ë€Us[€ 5|Œa€I>€,€˜–€g€Us0Ô= ¥}|j 5|= €,€ÕŸYà ŽÉj€ô$ÃÃô$Œa€= = ˜–€±€¤Ë€[€0Ô0Ôj0Ôjj 5˜–€±€˜–€˜–€€,€±€s÷€˜–€€,€¤Ë€[€¤Ë€±€Ûºçïçï±€¤Ë€˜–€[€˜–€Œa€g€€, Ž˜–€ô$€,€¤Ë€s÷€I>jŒa€[€$Ÿ$ŸI>s÷YÉj€€,€ 5½5€˜–€= I>Usg€s÷€g€jj= = ±€çïUs0Ô 5|jUs$ŸI>¥}}îb€ú>€ú>€ú>tP€€,îbîbtPîb‚¥}}tPtP‚+k€77775BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm·`‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUUUUUUUUUUUUUUAUUUUUEUUUUð c+Ä|Us¤Ë€g€¤Ë€ 57 ‚7 ‚±²+Ä~±²~7 € 5Usg€g€€,€I>Œa€Uss÷€€,€Us€,€$Ÿ 50Ô$ŸjI>= js÷€Us0Ô$Ÿ0Ô€,€½5€¤Ë€€,€Éj€±€½5€˜–€¤Ë€çïçï¤Ë€g€Œa$øØ–€½5€˜–Yô$¤Ë€˜–€½5€±€áÔ€±€Œa€s÷€s÷€a¨s÷€˜–€a¨ÕŸ€ÕŸ€g€¤Ë€g€= = jj7 ‚±²| 5= Œa€g€€,€€,€˜–€g€s÷€UsŒa€Œa€€,€ÕŸ€Œa€ô$áÔ€ÕŸ€¤Ë€$Ÿj 5ú—€ 5 5$Ÿ0Ô$Ÿ±²|0Ô 50ÔI>Usg€€,€s÷€Œa€ÕŸ€Œa€±€a¨0Ô$Ÿ7777>BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò(0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±°Œ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUPUUUUQUUUUUUUUUUUUUUUUUUð `jj$ŸI>Usa¨$Ÿ= = 0Ô0Ô€,€ÕŸ€áÔ€Us€,€€,€˜–€Uss÷€€,€UsUs0Ô±²~7 €$Ÿj 50Ôja¨j= I>€,€0ÔUsI>a¨ú—€$Ÿú—‚7 €…€I>Us 5Us= = 0ÔI>= I>Us$ŸI>a¨½5€ÕŸ€jj0Ôa¨Œa€€,€a¨g€= = jj+Ä| 5j0Ôjj= Usg€Us0Ô0ÔI>jjj$Ÿj 5j 5jjj0Ô0Ôa¨0ÔŒaYY€,€Uss÷€Usa¨UsUs$Ÿs÷YI—ô$½5€¤Ë€s÷€7777>BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò<0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUPUUUUUUUDUUUUUUUUUUUUUð `I>I>= g€€,€g€UsUsg€Œa€€,€˜–€±€½5€Œa€Usg€€,€€,€±€˜–€s÷€s÷€a¨€,€¤Ë€0Ô$Ÿ 5= s÷€j+Ä~±²~±²|g€0ÔI>= g€a¨I>$Ÿ0ÔI>j 5 5$Ÿj 5$Ÿ$ŸUsI>g€g€€,€ 5 5 5±²|+Ä| 5$Ÿjjú—€+Ä|= a¨˜–€= UsI>g€jj$Ÿj= I>a¨a¨g€Œa€g€g€€,€˜–€Œa€g€Œa€±€±€¤Ë€Œa€½5€¤Ë€ÕŸ€±€Éj€çï½5€½5 Žç€Œa€Œa€€,€g€€,€½5€€,€˜–€±€¤Ë€s÷€7777>BUFRæbÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒP0$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ý¶Û`‹JÚà†B˜èKŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUDPTUUUUð `˜–€˜–€¤Ë€Œa€s÷€Œa€s÷€s÷€Usg€¤Ë€€,€s÷€s÷€g€˜–€½5€±€Éj€s÷€s÷€s÷€Éj€½5€Éj€ÕŸ€¤Ë€€,€€,€s÷€Œa€¤Ë€½5€Éj€s÷€€,€= s÷€ÕŸ€Éj€Éj€g€s÷ Ž$øI—áÔ€ÕŸ€çïáÔ€¤Ë€ÕŸ€Œa€½5€¤Ë€½5€áÔ€˜–€s÷€g€±€±€€,€Œa€˜–€˜–€€,€¤Ë€áÔ Žô$ÕŸ€ÕŸ€½5€˜–€g€s÷€Uss÷€€,€= 5= = j$Ÿ0ÔI>UsUs= I>= ja¨Us0Ô 5 5ú—€±²|±²+Ä| 5±²| 5jj0Ô$Ÿ 5$Ÿjj$ŸI>0Ô7777>BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Òh0I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUQUQ@UUUð `= $Ÿ0Ôjj0Ô= I>= = $ŸUsI>I>0Ô= s÷€= = I>Œa€˜–€€,€Us¤Ë€Éj€g€¤Ë€±€¤Ë€˜–€ÕŸtP ޱ€ÕŸ€½5€ô$Éj€±€€,€s÷€s÷€˜–€¤Ë€½5€ô$áÔ€±€Uss÷€a¨s÷€˜–€a¨˜–€ÉjI—I—±€UsI>g€Œa€€,€s÷€= I>€,€a¨= 0Ô0Ô$Ÿ$Ÿ= g€g€g€a¨€,€g€a¨s÷€s÷€g€0ÔI>Us= g€s÷€g€0Ô 5 5j±²| 5 5$Ÿ$Ÿ 5 5 5+Ä|0Ô= ú—‚7 ‚7 ‚±²~7 ‚±²|j= j$Ÿ 5$Ÿ0Ô$Ÿ0ÔI>$Ÿ$Ÿ7777>BUFR&bÿ« fÒ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷€„!B„!B„!D!B„!B„!B†1ŒcÆ1ŒcÆ1ŒcÈB„!B„!B„! P‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUQUTPEUUQUUUUUUUUUUUUUUUð `$ŸI>I>g€s÷€s÷€¤Ë€ÕŸ€¤Ë€Œa€Œa€g€€,€a¨I> 5±²~7 ‚±²+Ä~±²~±²~7 € 5Œa€áÔ€0Ô$Ÿ 5+Ä|j$Ÿj±€ÉjY ŽáÔ‚±²| 5 5+Ä+Ä| 5ú—€= = = = I>s÷ƒ+Ä|s÷ú—ƒ+Ä}€…‚±²~±²| 5I>I>I> 5j+Ä|$Ÿ$Ÿ= I>UsI>Us€,€€,€˜–€s÷€a¨g€I>Us= Us˜–€ÕŸ€½5€s÷€Uss÷€g€a¨g€Œa€ÉjÃ=bŒºÉÃîb±Y±Y¥$ŒºY¤Ë€áÔ€áÔ€ô$1-UÌ$ø¤Ë€s÷€0Ô$Ÿ= = = a¨a¨a¨0ÔUs€,€Œa€ 5$Ÿ77775BUFRöbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@@"""""""""""#333333333334DDDDDfffffwwwwwwpŠ!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:§>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUUUUUUUUUUPQTUUUUUUUUUUAA@ð ` 5j±²|$Ÿ$ŸUs= s÷€˜–€˜–€Œa€a¨0ÔI>I>jg€0Ô0ÔUsUsg€0Ô$Ÿ= j 5$ŸUs 5 5 5j$Ÿ$Ÿj$ŸI>0Ôs÷€s÷€€,€g€UsI>I> 5 5+Ä+Ä|$Ÿj+Ä|$Ÿj 5ú—ƒ+Ä|I>$Ÿ€,Ãg€€,€a¨ 5 5= I>0Ô= g€Œa€˜–€¤Ë€¤Ë€½5€Œa€±€¤Ë€ô$ÕŸ€a¨±€ÕŸ€s÷€I>g€j= 5 5 5I>a¨€,€¤Ë€g€UsUsú—‚7 €±²+Ä|j€…€…€…‚7 ssú—€…€j= jú—ú—€…€O€7777$BUFRöbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@4@""""""""""3333333DDDDDDUUUUUUUUUUUUffffffffffffwpŠ×>”é[\1Е-sáN•µÀ˜éRØ×>”é[\ c¡*[æ5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUPPUUUUUUUTUUUUEð aú—ú—ú—‚7 €…‚±²~7 ú—s€…s€Œas‚7 ƒ+Ä|$Ÿ+Ä+Ä|0Ô= a¨€,€I>= 0Ô+Ä+Ä| 5 57 ú—‚±²|Œa€Œaú—€…s€…‚7 €…‚±²~7 € 5±²+Ä|UsjŒas€Œa€Œa‚7 ‚7 € 5I>½5€¤Ë€Usa¨= a¨$Ÿg€Us˜–€Us= +Ä|Us$Ÿ$Ÿa¨0Ôj$Ÿ7 ‚7 €7 ú—‚7 €jŒa€çïŒa€g€ 5$Ÿ 50Ô= I>I>s÷€= 0Ô 5ú—‚7 €…‚±²~±²~±²~7 €Us±€ÕŸ€Œa€s÷€s÷€€,€g€jj$Ÿ$ŸI>±€¤Ë€€,€s÷€Œa€ 5±²|Uss÷€7777$BUFR&bÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒBUUUUUUUUUYÎsœç9ëZÖµ­kZÞ÷½ï{Þ÷½ï{Þ÷½ï{ç9Îsœç9Îsœç9Îsœï{Þ÷½ï{Þ÷½ï{Þ÷½B„!BŠ2ÇBT¶¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUPUUUUUUUUUUUUUUUUUUUð `= Us¤Ë€Éj$øUÌUÌYI>¥$±YÉÃŒºtPI—Œºb=b1-ÃÃUÌ Žô$áÔ€áÔ€çï±€½5€Œa€s÷€= Us= = j0ÔgÂYÕŸ€¤Ë€Œa€s÷€áÔ€˜–€½5€g€˜–€s÷€+Ä+Ä|$Ÿ$Ÿa¨UsI>jj 5= Us˜–€s÷€˜–€±€s÷€s÷€a¨˜–€Œa€¤Ë€½5€ÕŸY$øÃÉj€±€˜–€Œa€¤Ë€¤ËÃtP˜ïŒºI—çï ŽçïÕŸ€áÔI—Ys÷€˜–€áÔ Ž1-ÃáÔ€çïŒa€Éj1- Ž=bŒº½Ž€… ŽbUÌb=bI—ÃÉj€±€Œa€±€áÔYY$ø$øI—77775BUFRæbÿ« fÒ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUTPAUUUUð aÃ1-Yô$1-UÌI—1-$øô$Éj€s÷€€,€$Ÿj 5a¨½5€çïçï½5€˜–€Usg€a¨s÷€g€Œa€Éj$øÃ1-$øÃô$çïáÔYÕŸ€ÕŸ€ÕŸ€±Y$ø ŽÕŸ€˜–€¤Ë€g€g€˜–€s÷€s÷€ÕŸ1-1-½5€Éj€áÔYçï½5€s÷€Usg€s÷€s÷€˜–€Us= I>= = 0Ô$Ÿj= $Ÿ$Ÿ0Ôj$Ÿ 5ú—€±²}ú—‚±²+Ä~±²| 5±²~±²+Ä~±²}€…‚±²~7 ‚7 ‚±²|$ŸUss÷€0Ô+Ä~±²| 5±²|7 €j0Ôa¨Œa€˜–€ÕŸ€½5€ÕŸ€±€g€¤Ë€€,€½5€ô$ÕŸ€Œa€Éj€7777ŽBUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUQUUUUUUUUUUUUð `ÕŸ€áÔ€ÕŸ€s÷€a¨s÷€I>0Ôa¨a¨Œa€¤Ë€¤Ë€±€g€ 5jI>= j= a¨s÷€a¨UsUs$Ÿ= $Ÿa¨UsUsUsg€€,€s÷€I>I>0Ô= 0Ô$ŸI>g€€,€€,€€,€€,€€,€g€I>j±²|±²~±²+Ä+Ä|j0Ô0Ôjj$Ÿ$Ÿ0Ô$Ÿa¨a¨a¨0ÔI>= I>I>= j0Ô+Ä|j0ÔI>s÷€˜–€€,€UsUs= €,€˜–€Œa€˜–€g€s÷€€,€I>0Ô$ŸUs$ŸI>Usg€€,€˜–€±€±€¤Ë€¤Ë€¤Ë€˜–€a¨Œa€gÂYI—I—ÃÉj€ÕŸYÉj€çïáÔ€Éj€˜–€Œa€˜–€7777ŽBUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€40I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt&S¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUUUUUUUUTUUUUUUUUUUUUUUð `çïÉj€½5€Éj€¤Ë€¤Ë€€,€¤Ë€Œa€UsUs0Ôú—€…ss€…€…‚7 €0ÔŒa€±€½5€Éj€Éj€½5€±€±€¤Ë€ÉjYçï¤Ë€¤Ë€Œa€s÷€s÷€Us= I>j0Ô= g€½5€g€0Ô= I>I>Usa¨= 0Ô$Ÿ±²~7 ‚±²~7 ú—ú—‚7 ú—ú—sƒ+Ä|a¨€,€±€çï±€Œa€I>a¨I>a¨¤Ë€áÔ€˜–€˜–€½5€ÕŸYÕŸ€¤Ë€s÷€Éj€s÷€Œa€¤Ë€Éj=b ŽçïÉj€½5€áÔ€¤Ë€Éj€ÕŸ€áÔÃ$ø=bUÌ ŽYÕŸ€˜–€˜–€Éj€¤Ë€Éj€¤Ë€ÕŸ1-=bY ŽYçïô$ Ž Ž7777ŽBUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€H0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUTEUUUTDUUUUUUð `ô$áÔ€çïÉj€½5€çï$øYYçïYáÔ€±€˜–€g€g€g€çïI—1-1-=bUÌ$ø1-Yà Žô$±€˜–€±€¤Ë€¤Ë€Œa€Usa¨a¨˜–€a¨Uss÷€Us0Ôa¨= a¨j 5 50Ô$Ÿj$Ÿg€˜–€±€¤Ë€€,€˜–€±€ÕŸY1-1-=bU̽5€¤Ë€Us0Ô$Ÿj0Ô+Ä|+Ä|= Œa€Œa€˜–€˜–€çïô$¤Ë€±€˜– ŽUÌÃçïUs$Ÿj±²|+Ä|j±²+Ä|0Ôa¨s÷€a¨= a¨€,€€,€Us0Ô= 0ÔI>Œa€a¨a¨Us½5€±€Œa€jj±€±€çï$ø7777ŽBUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò€`0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠt%MsáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUTUUUT@UUPUUUUUUUUUð aUÌn6I—ç€¤Ë€çïbbô$€,€˜–€çï½5€Usa¨Œa€0Ô0ÔI>s÷€½5€˜–€Œa€€,€ÕŸ€I>= I>a¨±€±€a¨a¨0Ôj 5+Ä~±²}ú—ú—‚7 ‚±²|jj$ŸUs= 5jj€,€çïÃÉj€s÷€$Ÿ 5+Ä|7 ú—‚7 s‚7 ssú—ú—ú—ú—€…ƒ+Ä+Ä| 5Uss÷€ÕŸý5€ 5½5€I>7 ‚7 €0Ôa¨ Ž ŽçïáÔ€€,€€,€a¨±Yn6˜ï€…Œº€…b ŽbÃñ€Œa€Uss÷ ŽI—ÃYçïô$ô$ Ž ŽYô$7777ŽBUFR&bÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò‚UUUUUUUUUUUUUUUUUU^sœç9Þ÷½ï{Þ÷½ï{Þ÷½ï{ï{Þ÷½ï{Þ÷½ï{Þ÷¼„!B„!B„!B!B„!B„!B„0‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUTTUUUð a ŽYô$áÔ€áÔ€¤Ë€±€Œa€€,€s÷€$Ÿja¨˜–€±€ÕŸ€±€Éj€¤ËÃYÃ=bÃY½5€½5€s÷€g€€,€UsUsI>Us= Us½5€ô$ô$$øç€¤Ë€ÕŸY1-Y$ø1-1-=bÃY Ž$ø=b$øÃYçïçïáÔ€ô$áÔ€½5€s÷€¤Ë€ÕŸ€Éj€ÉjYáÔ€¤Ë€¤Ë€I>g€½5€¤Ë€Œa€= 0Ô$Ÿjs÷€áÔ$øYô$1-çï€,€¤Ë€Œa€Œa€çïô$˜–€Us= 0ÔI>0Ô7 ƒ+Ä~±²|±²+Ä|˜–€Usa¨0Ô 5+Ä|$ŸŒa$øI—I—UÌ1-Ãô$Y¤Ë€I>77775BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀ0I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ …1Е-sáN•µÀ …1Е-te:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `$Ÿjj0Ô€,€ô$1-YçïÉj€¤Ë€áÔ€Œa€ô$€…Õø±YÉÃÉÃb$øÃ ŽYÉj€˜–€Éj€¤Ë€áÔÃI—$øô$ÕŸ€½5€ÕŸ€ô$áÔ€ÕŸ€g€€,€¤Ë€UsUs= 57 ƒ+Ä|= g€˜–€ô$UÌ=bI—1-1- Ž$ø1- Ž=bçï¤Ë€Us$Ÿ$ŸI>I>$Ÿ 5 5$Ÿa¨áÔ€áÔ€½5€Œa€a¨a¨Us€,€s÷€çïô$Éj€Éj€˜–€Œa€±€˜–€ÉjÃY$Ÿ€,€€,€Œa€áÔ$øÃçïáÔ€ÕŸ€ÕŸ€Éj€Éj€±€Œa€Œa€€,€Œa€áÔ€±€±€˜–€ÕŸ€½5€Us= g€˜–€ô$ ŽYÕŸ€7777BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀ$0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUTUUUUU@UUUð `ô$½5€çï$ø=b=b1-I— ŽÕŸ€áÔ€½5€áÔ€±€Éj€Éj€çï½5€g€= 0Ô= = a¨Œa€= $Ÿjs÷€½5€ÕŸ€Œa€¤Ë€ô$bÃŒa€a¨˜–€g€0Ô= a¨g€՟€áÔ€Éj€½5€s÷€g€s÷€Éj€áÔ ŽYô$Y ŽáÔ€±€Usa¨$ŸI>$Ÿj 5g€՟€ÕŸ€±€Éj€ÕŸ€ÕŸ€¤Ë€Œa€ô$UÌ=bÃô$çïáÔ€½5€˜–€I>= +Ä|j 5Us±Y$ø1-1-çïáÔ1-$øtP$ø1-çï ŽÉj€±€Œa€I>7 ú—€…€…ú—‚7 €= €,€áÔ€g€Œa€ÕŸ€áÔ€ô$ÕŸÃ$ø¤Ë€7777BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀ80’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÛmÛ`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶¹ðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `±€˜–€g€Usj$Ÿ+Ä~±²|a¨±€çïÉj€ô$ÕŸ€Œa€Œa€±€áÔ€ô$$ø$ø$ø1-1-$ø$øtPbà ŽáÔ€±€˜–€Éj€áÔ€½5€¤Ë€½5€¤Ë€¤Ë€±€ÕŸ€áÔ€çïÉj€ÕŸ€¤Ë€¤Ë€˜–€½5€Œa€± ŽÕŸ€±€a¨g€˜–€s÷€€,€s÷€˜–€±€±€Œa€áÔ€áÔ€ô$Y1-YYô$Yô$ô$çï±€±€˜–€˜–€˜–€½5€±€½5€Éj€½5€˜–€€,€Œa€ÕŸ€áÔ€ÕŸ€ÕŸ€áÔ€Éj€¤Ë€±€±€˜–€€,€a¨I>UsI>a¨a¨g€s÷€€,€˜–€¤Ë€¤Ë€¤Ë€Éj€½5€¤Ë€€,€Uss÷€s÷€a¨a¨a¨a¨= 7777BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀP0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUQUUUUUUUUUUUUUUð `UsI>0Ôs÷€a¨Usg€¤Ë€¤Ë€¤Ë€˜–€±€±€ÕŸ€ÕŸ€ÕŸ€áÔ€Éj€ÕŸ€¤Ë€€,€s÷€a¨¤Ë€Œa€g€g€s÷€Œa€€,€€,€s÷€¤Ë€ÕŸ€ÕŸ€Éj€Éj€ÕŸY½5€€,€Uss÷€g€s÷€g€= j+Ä|a¨s÷€g€UsUsg€s÷€˜–€Éj€¤Ë€Œa€˜–€˜–€I> 5+Ä|j0Ô= ±²+Ä|0Ôa¨s÷€g€s÷€Œa€= s÷€˜–€Us€,€¤Ë€Œa€¤Ë€½5€s÷€Us˜–€€,€Œa€áÔ€½5€Œa€˜–€½5€ÕŸ€Œa€s÷€Œa€€,€Éj€Éj€a¨s÷€ô$YçïçïáÔ€€,€s÷€Œa€€,€s÷€g€I>g€¤Ë€Œa€˜–€½5€¤Ë€¤Ë€ô$7777BUFRæbÿ« fÒ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÀd0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUPUUUUPUUUUUUUUUUUUUUUð a=bÃÃ1- Ž=bUÌ$øY±€½5$øÉj€¤Ë€€,€€,€Œa€±€Éj€áÔ€áÔ€çïÕŸ€½5€ô$ÕŸ€çïYçïçïÉj€Œa€Œa€Us$Ÿjj±²~7 €…‚7 €= I>I>= a¨a¨a¨Œa€¤Ë€Éj€˜–€s÷€a¨g€Us= $Ÿj 5±²}ú—ú—‚±²| 5a¨Œa€±€±€½5€½5€s÷€½5€ÕŸ€ô$Yô$ô$ÕŸ€˜–€¤Ë€g€Us˜–€€,€a¨s÷€˜–€áÔ1-1-UÌ=bI—=bÃÃà Ž$ø$ø$ø=bÃô$ô$YY±€a¨Uss÷€s÷€½5€ÕŸ€½5€Éj€±€Œa€±€¤Ë€±€˜–€s÷€Œa€±€7777BUFR&bÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒÂUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU^÷½B„!B„!B„!„!B„!B„!CÆ1ŒcÆ1ŒcÆ1Œd!B„!B„!B…)JP‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUUUUUUUUUUUUUUTUUUUUUð `Éj€±€±€€,€a¨= 7 €…s€…‚±²}ú—‚7 € 5+Ä+Ä+Ä+Ä+Ä|I>Us0Ô0Ô$Ÿ 5 5= +Ä~7 ú—€…‚7 €…ƒ+Ä|$Ÿ= Us$Ÿg€I>= a¨a¨±€˜–€Œa€a¨˜–€€,€I>j+Ä~7 ú—‚7 €js÷€ÕŸ$øÃÕŸ€áÔ€±€áÔ$øUÌbbÃô$ Žô$±€½5€½5€¤Ë€¤Ë€Œa€g€s÷€±€çïçï Žçïs÷€s÷€¤ËY ŽçïYÕŸ€s÷€Œa€a¨a¨0Ôj0Ô 5±²|Uss÷ ŽUÌ1-ô$çïÃ$øY=bUÌI—UÌ$ø1-Ãçï½5€˜–€¤Ë€s÷€g€a¨77775BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUTUUUUUUUUUUUUPUUUUUUUð `= Usg€g€g€s÷€$Ÿ0ÔI>€,€€,€€,€€,€s÷€Usa¨I>= j7 ‚7 ú—ú—€…‚7 ‚±²|$ŸI>I>Us= jUs0Ô0Ô0Ô$Ÿ0ÔI>= s÷€˜–€j±²~7 €…€…€…€…ú—ú—‚7 ‚7 ú—€ 5j$Ÿ 5 5j$Ÿ$Ÿ$Ÿ$Ÿj±²}ú—ú—ú—€ 5= Us0Ô0Ôjj 5$Ÿ= I>Usa¨a¨ja¨Us$ŸUss÷€$Ÿ+Ä+Ä~7 €0Ô0Ô0Ô= $Ÿ 5j= ja¨s÷€UsI>= = 5j 5 50Ô 5j$Ÿ= g€s÷€s÷€I>a¨a¨7777$BUFR¦bÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!RLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò,0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýàY$øÈ)2à˜–‚“. #`€,ÏÞ?xã`Œa‚²?xã`gÂUÌÈ Œa‚²Æ#`Œa‚² ‰h&% ˜–‚“. L¸&% ¤Ë‚1†È gŸ |(ã`[Ÿ È ¤Ë‚² ‰h&% ¤Ë‚Ä ÓX2Z Éj‚Ä –¨2Z Ûºnè –¨2Z ÕŸƒ%ª –¨2Z ÛºV~ » 9ûÀÛºV~B@6î€ÕŸƒnè » = ÛºŸ¼ » 9ûÀÉjÏÞW0 5 5n6Ið’||(ýà€,Ÿ W0ã`[UÌW0O€[n6Ð 'ÀI>$ø†  50ÔÃP†  @a¨Ðð g‚²Æ)2à¤Ë‚“. &% ±‚ôÖ Yø,@ ¤Ë€7777>BUFR¶bÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ò@0$’I$’I$’JI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹[\ÈS RØ×>”é[\ÈS RØ×Â2+k€" c¡*[çÂ2+k„C!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ýà\Ï…n6>¸Ø 'À 5O€I>²ˆ Yø-P9ûÀ^šÀ˜–I—1†ˆ„€= mÝÛº·t%ªKTÆ~ð 'À$ŸUs·Ÿ¼dpÐ'¬@C#€zÉj1-Ĭü » ýà@@mÝYèHV~ÝÐ –¨Œ0ð -ÆÀI>Y“.é¬È øPã`*¹€[€çï%ªÝÐ » ¦°)2àF0Às÷Ó.¬ü ³ð2Z X€@±I—V~¬ü Yø„€5gàReÀ¤Ë«?%ªÄ´ ™p2Z ReÀ˜–€çïÏÞÄ´ ‰hÐ&% F0À˜–I—ÄKT ÓXw@2Z ^šÀ˜–Ã1†dÆ øPð 3á@s÷1-bZé¬?x 'À 'À„€ 57777 BUFRæbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒX0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUTEQUUUPDUUUUUð `jj= 0ÔI>g€a¨a¨€,€½5€Éj€áÔ€Éj€áÔYçïYa¨= 7 ƒ+Ä| 5I>I>Œa€€,€¤Ë€g€€,€Éj€áÔ€Éj€½5€±€¤Ë€Œa€g€Usa¨a¨a¨7 €…ƒ+Ä| 5a¨€,€¤Ë€s÷€g€€,€€,€€,€¤Ë€˜–€Usa¨I>j$Ÿ+Ä| 57 €= Usj+Ä|$Ÿ= a¨I>= j= = j 5 5 5 5 5±²+Ä| 5+Ä|7 €…€…sú—sú—€…s€jg€I>I>˜–€g€s÷€˜–€a¨˜–€€,€7 €7 €…‚±²+Ä|0Ô0Ô$Ÿja¨= 0Ôg€áÔ€7777$BUFRfbÿ« fÒ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÒUUUUUTD»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»]kZÖµ­ï{Þ÷½ï{Þ÷½ï{Þ÷¾sœç9Îsœç9Îsœç9Î÷½ï{Þ÷½ï{Þ÷½ï{ß{Þ÷½ï{Þ÷½ï{Þ÷½à‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­® …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTUUUUUUTUUTUUTUUUQUEUUUUð aY±€ÕŸ ޽5€¤Ë€j$Ÿ0Ôj±²+Ä~7 ‚±²|jj0Ô0Ô$Ÿ0Ô= UsUs= = UsÕŸYô$¤Ë€¤Ë€g€jjI>I>= $Ÿ0Ô$Ÿ±²|ja¨Œa€áÔ€ô$s÷€s÷€I>0Ô7 ú—ú—€±²~±²+Ä|0Ôg€$Ÿj0Ô$Ÿ 5 5j 5±²+Ä+Ä~7 ú—€…ú—ú—‚7 ú—€…‚±²|$ŸI>I>$Ÿjj$Ÿ0ÔUsI>$Ÿ0Ô0Ôj+Ä|$Ÿa¨I>= 5 5±²| 5$Ÿa¨Éj€˜–€±€½5€ô$ÕŸ=báÔY€,€Us= j7777BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$–Ûm¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðEUUUUT@UUUUUUUUUUUUUUUUUUUUUUUUýà` 5| 5$ŸI>çï1-Ûºô$ÃÃÕŸ€ÛºY±€ÕŸ€ÕŸ€ÕŸ€UsI>0Ôj+k€ 5+kîbîbtP‚+k€ 5g€[€UsŒa€¤Ë€ÛºYYY1-ÃçïÃYÕŸ€ÕŸ€˜–€€,€s÷€Us$Ÿ 5= €,€€,€Éj€¤Ë€±€˜–€˜–€¤Ë€½5€¤Ë€ô$çïÛºÛºçïY ŽYô$ô$Éj€½5€ÕŸ€ÉjYô$Yô$ ŽçïÕŸ€ô$$øb=bÃY1- ŽÉj€Éj€±€ô$YçïÛº±€Éj€½5€çï ŽYÉj€çï$øÃ$ø ŽÛºÉj€˜–€˜–€Œa€g€ 5 5 5UsUs˜–€˜–€$Ÿ7777$ŸBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUUUUUUUTUUUUUUUUUUUUUUUUUUUUU `$ŸjZ|OX€Éj€ÉjÃô$çïô$Ûº½5€˜–€¤Ë€g€[€€,€±€Éj€çïÃÃçïÛº ŽÛºÉj€ô$ô$çïçïçïÉj€€,€OX€= = $Ÿ™HZ| 5j€,€½5€½5€çïçï½5€˜–€Éj€ô$ÃI—$ø ŽÃYÛºô$ô$Éj€½5€Éj€€,€j$Ÿ€,€Ï… Ž$ø Ž ŽYÏ…ô$Ã$ø1-Ãà ŽÏ…Éj€±€= OX€$Ÿ[€Œa€Œa€±€±€Ûº±€¤Ë€s÷€s÷€˜–€Œa€Œa€˜–€½5€Ï…YYô$çïÏ…çïô$ô$½5€¤Ë€¤Ë€Œa€¤Ë€¤Ë€˜–€±€Œa€Œa€Œa€Œa€±€˜–€½5€g€7777$ŸBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@00’I$’I$’JI$’I$’I$“m¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶Ûm·m¶Û`‹:V×D2ÇBX×>”é[\ÈS RØ×>”é[\ÈS |#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUPUUUUPUUUUTUUUUUUUUUUUUUUUUð `s÷€±€a¨I>g€+Ä~±²+Ä}ú—‚±²| 5Us½5€ÕŸ€˜–€s÷€Œa€¤Ë€½5€Œa€s÷€g€¤Ë€a¨0Ôj= = +Ä+Ä|0ÔUs˜–Ãô$áÔ€a¨g€I>¤Ë€½5€ÕŸ€ÕŸ€¤Ë€¤Ë€I>$ŸI> 5+Ä}ú—‚7 €…€…ú—‚±²|ja¨a¨g€g€Éj€˜–€a¨g€Œa€¤Ë€g€g€a¨I>= €,€ô$$øI—Ã1-±€Œa€½5€çïô$Yô$ÕŸ€Us 5$Ÿ 5ú—€…ú—‚7 € 5I>s÷€Usg€€,€s÷€ŒaY$øbUÌ=bÃY ŽÕŸ€±€ÕŸ€½5€a¨g€I>UsI>s÷€çïáÔ€7777$ŸBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@H0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTUUUUUUUUUQUUUUUUUUUUPUUUð `Éj€±€˜–€Œa€Œa€s÷€€,€Us= 0Ô$Ÿ+Ä+Ä~±²~7 € 5±²~±²~7 ‚7 €I>jjI>Uss÷€I>a¨$øI—ÕŸ€ÕŸ€áÔ€áÔ€¤Ë€s÷€˜–€7 ‚±²~7 ‚7 €j$Ÿ= Usa¨s÷€€,€ô$Y$ø=b$øÉj€€,€a¨g€ 5±²|+Ä}€…‚7 €jI>g€Œa€a¨€,€s÷€¤Ë€¤Ë ŽÕŸ€ô$áÔ€ô$ Žô$ô$1-1-1-ç€a¨= g€Œa€áÔ€±€Œa€€,€˜–€s÷€Œa€½5€½5€±€¤Ë€€,€Us0Ô$Ÿ±²}€…‚7 €= 5 5a¨±€ô$$ø½5€½5€áÔ€çï$øUÌ1-I—7777$ŸBUFRöbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@\@"""""""""""#333333333334DDDDDDDDDDDEUUUUwwwwwwˆˆ€‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸D2ÇBX×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUPUUPUQ@UUTUUUUUð a=btPÉñY€…n6ÃYÕŸ€Éj€±€¤Ë€¤Ë€½5€áÔ$øô$ÕŸ€ÕŸ€Éj€áÔ€ÕŸ€çïÃçï±€Éj€¤Ë€a¨€,€g€±²~7 ú—ú—‚7 € 50Ô0Ô= g€= $Ÿj0Ô= €,€UsŒa€˜–€±ÃÉj€g€€,€0ÔUs+Ä~±²|jI>jj 50Ô 5 5±²+Ä|I>$Ÿj 5a¨±²|s÷€Us±²}€…ú—ú—€ 50Ôg€¤Ë€±€g€0Ô 5= g€s÷€I>$Ÿj7 €…ss€…s€Œasú—€jj˜–€g€I>Usa¨g€I>= ±€Usg€g€Œa€g€Œa€g€I>7777jBUFR&bÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓBUUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷½ï{ÀB„!B„!B„"„!B„!B„!CÆ1ŒcÆ1ŒcÆ1Œd!B„!@ŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUTUEUTUUUUUUUUUUUUUUð `a¨±$øbn6YáÔYô$ Ž=bbtP˜ï½Ž±Y$øáÔ€çïa¨= 0Ô 5j= s÷€½5YçïÉj€½5€˜–€a¨€,€˜–€€,€Éj€ÕŸ€½5€˜–Ø–€0Ô 5jj+Ä~±²| 5I>I>0Ô 5+Ä|$Ÿ0ÔI>Us0Ô0Ô7 ‚±²}ú—‚7 ‚7 € 5g€çïÕŸ€¤Ë€= I>g€0Ô= I>˜–€˜–€çï±€a¨$ŸI>j 5j$Ÿ 5 5$Ÿ€, Ž=bÉj€±€Éj€g€a¨a¨a¨áÔ€ÕŸ€¤Ë€˜–€a¨a¨Usa¨a¨±€a¨$Ÿ$Ÿs÷Yb±Y€…UÌI—1-7777²|BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUU@UEUUUUUUUð a$øÃ=bŒº½Ž½Ž½Ž½Ž‚²¥$¥$±Y˜ïŒºbÃ$ø1-I—$øÃYÃô$à Žô$$ø Ž$ø ŽáÔ€ÕŸ€áÔ€áÔ€áÔ€˜–€I>= UsŒa€ÕŸ ŽI—1-1-çï½5€½5€ô$Y1-UÌI—$ø=bÃY½5€¤Ë€€,€Us$Ÿ 5jUs€,€Éj ŽÕŸ€Œa€˜–€˜–€g€s÷€¤Ë€ÕŸ€ô$ô$¤Ë€€,€a¨I>0Ô±²}ú—‚7 ú—€Œa€jj 5I> 5+Ä|UsÉj€¤Ë€Éj€áÔ€áÔY$øáÔ€Éj€¤Ë€±€Œa€Œa€½5€áÔ ŽŒºÃáÔ€½5€±€Éj€ÕŸÃô$½5€Œa€Œa€7777Ë€BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€(0$’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹[\ÈS [çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUPð `¤Ë€€,€a¨I>$Ÿ 5= ½51-=b1- Žô$1-ô$=b=b1-I—n6tPtPI—1-Ã Ž ŽçïáÔ€ÕŸ€çïY=bÃáÔ€±€Éj€çïYô$ÃÃçïçïÉj€½5€áÔ€s÷€0Ô 5$Ÿ0Ô= €,€¤Ë€¤Ë€±€€,€¤Ë€çïÕŸ€˜–€¤Ë€€,€±$ø1-tPI—áÔ€ÕŸ€ÕŸ€çïáÔ€Éj€±€½5€ÉjÃI—I—$ø$øçïa¨˜–€Éj€¤Ë€Éj Ž1-1-=b$ø1-1-$øYáÔ€ÕŸ€½5Y Ž1-=b$øY½5€= j 5$ŸI>a¨0ÔUs0Ô= Usj+Ä~±²~7 ‚7 ‚7 ‚±²|7777Ë€BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUUUAUUUUUUUUUUUUUUUUUUUUUUUUUUýàc| 5 5j| 5 50ÔÕŸ€ô$ÛºÉj€ÕŸ€Éj€˜–€˜–€j 5¥}~+k€0Ô[€Éj€s÷€Us= j0ÔI>I>€,€çïô$ÕŸ€Éj€¤Ë€s÷€ÕŸ€±€Œa€½5€¤Ë€Éj€˜–€Éj€ÕŸ€ÕŸ€±€[€[€[€g€€,€Œa€±€ô$çï±€±€ÛºÉj€¤Ë€Œa€€,€˜–€½5€ÕŸ€ÛºY1-I— ŽÛº½5€˜–€¤Ë€Œa€¤Ë€ÉjÃÃ1-1-$øÃÃÃYô$Éj€Éj€Éj€ÕŸ€½5€Éj€ÕŸ€Éj€ÛºÉj€Éj€ÛºY ŽI—b1-UÌ1-$ø=bI—b=bUÌ=b$ø=bI—UÌI—ÃÃô$Y7777Ë€BUFR¶bÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€T0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’Km¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Êt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@)2à]Ÿ c º<˨1—Pf;àÌwÁC|‚n28¡ ~ð\À*¹€LK@Ï…1†Ä´ÆÈàýà0Ô[€ÃPèHÑB ,Žø+|Ð)2àŒaY²Ð?x øP\À#`@@s÷€·n6·tIðdp 'ÀO€ 5a¨zÄÈ&% z$øŸ ÏÞÜl28“à ®`9ûÀŒaI—nèc õˆ q°ã`w@OX€ž±=bc B@ýà6î€g€υ1-bZŸ¼Æ q°Ö w@6î€Ï…bZ¸Ø ‰hýà@@€,à @ÝÐ#`I>¡¾A1-IðÄ´¡ Èà C#€Œa1-bZÝÆÈà!‘À6î€mÝYIð ò 'Àð C#€Œa Ž7777bBUFR&bÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó‚UUUUUUUUUUUUUUUUUUUU]kZÖµ­kZÖµ­kZÖµ­ï{Þ÷½ï{Þ÷½ï{Þ÷°„!B„!B„!BB„!B„!B„!ŒcÆ0Šˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUTUUUUUUUUPð a ŽI—1-=b$ø1-=bI—bŒºb$ø$øI—=bI—1-ŒºÕøÕø±Y€…UÌ=bÉj€Œa€s÷€Usg€Œa€ŒaYÕŸ€½5€s÷€a¨a¨Usg€s÷€s÷€a¨I>0Ôa¨I> 5j= = 0Ô= 0ÔI>Us€,€s÷€Us= I>I>0Ô0Ô$ŸI>Us= ¤Ë€½5€ÕŸ€ô$ ޽5€I>j= $ŸjI>I>$Ÿ 50Ô 5 5±²| 5g€çï$ø½Ž½ŽbUÌ$ø1-çïáÔYY Ž€…½ŽI—ÕŸ€ÕŸ€ÕŸ€€,€Œa€½5€Éj€Éj€áÔ€çïYYÕŸ€±€g€j±²~7 ‚±²+Ä|0Ôs÷€7777²|BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀ0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUUUUUUUUUUUUUUUUUUTð `˜–€˜–€±€ÕŸ€Œa€½5€±€±€½5€±€¤Ë€˜–€s÷€I>= 0Ô 57 ‚7 ƒ+Ä|ŒaÃI—$øÉjUÌ=bô$1-UÌUÌI—tPbI—n6¥$I—Ãô$ÕŸ€±€˜–€½5Y$øI—½5€±€s÷€0Ô= I>g€Œa€ÕŸ¥$±YI—$øáÔÃYÉj€s÷€I> 5j= g€˜–€€,€g€UsI>I>€,$øÕŸ€ÕŸ€a¨±€g€= = 5±²}ss€Œas€…€js÷€Œa€s÷€I>I>a¨$Ÿ$Ÿ$ŸI>€,€Usj0Ô= $Ÿ7 ƒ+Ä~7 ú—€…‚7 ‚7 €j 5±²+Ä|jjj7777,€BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀ$0I$’I$’I$”’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUU@UUUU@UUUTUUUTUUUUUUUUUUUð `I>I>I>a¨= 50Ô= $Ÿ+Ä}ú—€…ú—€I>±€ÕŸ€Œa€UsI>UsI>I>a¨€,€½5€Éj€çïa¨a¨g€g€j±²~7 ‚7 ‚±²|0Ô€,€¤Ë€Œa€I>I>a¨ 5jj0Ô= a¨a¨Us0Ô+Ä+Ä~±²~±²}ú—‚7 €a¨€,€˜–€g€a¨Usg€s÷€s÷€I>a¨s÷€I>0Ô0Ô= j+Ä+Ä~±²+Ä~7 € 5I>½5€¤Ë€I>I>g€I>= j$Ÿg€Usg€I>Us= 0ÔI>= $Ÿj= I>Œa€½5€ô$çïUs$Ÿ$Ÿ$ŸjUsa¨˜–€˜–€½5€g€a¨Usg€7777,€BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀ<0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUT@UUUUUUUUUUUUð `Éj€s÷€˜–€€,€s÷€Œa€½5€0Ô0Ô= jjj0ÔUs0Ôa¨€,€€,€Œa€g€= Us0ÔUsÉj€±€˜–€g€˜–€¤Ë€¤Ë€˜–€Éj€ÕŸ€0Ô= = I>Œa1-ŒºI—tPUÌb=bb1-ÕŸ€áÔ€áÔYn6n6I—Y½5€Éj€¤Ë€½5€±€±€½5€Éj€˜–€g€$Ÿ$Ÿ$Ÿ+Ä|+Ä~±²~±²~7 €$Ÿg€a¨€,€= I>Us= a¨a¨I>Us½5tPâ-±Y$ø1-=bn6b$ø ŽYô$I—²½Ž‚ çUÌ ŽYô$ô$ÕŸ½Ž‚V%Ê‚úð‚½ç‚½Ž±Y˜ï˜ï˜ï±Yâ-ÉÀ…€7777,€BUFRÆbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀP0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$¶Ûm¶Ûm¶ÐŠ•-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Ж¹ðŒ§JÚà†B˜è[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@&% `çï¤Ë€˜–€±€·$øYà ŽC|=btP=bYÃP˜–€€,€¤Ë€g€˜–€·çïÃPg€C#€jjj 5j0Ôg€±€Ûºô$ç€C#€jj[€s÷€˜–€·±€·˜–€¤Ë€€,€€,€ 5$Ÿ0Ô6î€C#€C#€s÷€·Œa€C#€C#€g€s÷€Ûº$ø÷·˜–€ÃPYC|€Œa€0Ô$Ÿ$Ÿ 50Ô$Ÿ0ÔC#€g€¤Ë€¤Ë€±1-$ø˜–€˜–€g€g€s÷ Ž¤Ë€·çï6î€g€OX€Œa€Ï…±Y‚%Qht‚P ‚=»Ü½Ž½ŽtPh[æC|1-˜ïÏÞÛº·˜–€ÛºÏ…çïYO±ÏÞô}é7777±YBUFRÆbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀd0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð b çîb‚ çb=b1-ÃY$øn6â-˜ï€Œa€UsI>UsUsI>a¨±bŒº ŽÕŸ€áÔ ŽI—$øáÔ€ÕŸ€áÔ€ô$ô$YÃ=b Ž= I>= I>I>g€s÷€±€ÕŸ€Éj ŽUÌäˀs÷€$Ÿ0Ôa¨±€±€˜–€s÷€s÷€Uss÷€€,€˜–€ÕŸ€ÕŸI—ô$ÕŸ ŽY½5€çïŒa€¤Ë€g€€,€˜–€½5€çïÃ=bŒºI—b˜ïŒºÕøÕøtP=bÕŸ€ô$áÔ€áÔ€áÔ€áÔ€½5€¤Ë€˜–€Œa€çïI—Us0ÔUsUsI>= I>a¨€,€€,€Œa€s÷€0ÔI>I>s÷€s÷€Usj= ±UÌ7777±YBUFR&bÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÂUUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷½ïx!B„!B„!BB„!B„!B„1ŒcÆ1ŒcÆ1ŒcÈB„!B„!@Šc¡*[çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUEUUUUUUUUð atPîbâ-$øÕŸ€˜–€Œa€˜–€˜–€½5€çïô$$ø=bUÌn6tP€ô$¤Ë€a¨a¨a¨I>±€ô$ ŽY½5€s÷€s÷€a¨I>Usa¨g€I>0Ô$Ÿj±²}ú—ú—ú—‚±²|= s÷€˜–€s÷€I>a¨s÷€Us= I>s÷€s÷€a¨áÔYn6=bÕŸ€s÷€g Ž ŽÕŸ€çïY1-áÔ€Éj€Œa€g€UsI>g€¤Ë€Éj€Éj€±€Éj€ÕŸ€¤Ë€¤Ë€I>I> 5+Ä|jg€Éj€ÕŸ€Éj€€,€€,€g€€,€s÷€Usa¨I> 5$Ÿ0Ôj= $Ÿ0ÔI> 5±²|I>s÷€€,€I>UsI>0Ô= Us€,€g€Uss÷€Éj€7777²|BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó0’I$’I$’II$’I$’I$“m¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶Ûm¶í¶Û`‹:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUPQU@UQUUPUUUUUUUTUUUUUUUð a Ž=bY$øÃçï±²~±²~7 ‚±²~±²|7 ‚±²~±²+Ä~±²~±²|±²| 5$Ÿ+Ä|+Ä+Ä~7 ‚±²~7 ‚±²~7 €= s÷€g€$Ÿj±²~±²~7 ‚±²| 5 5 5$Ÿ 5 5+Ä| 5j½5ÃÃI—Éj€j0Ô±²~±²|jj= g€g€Usg€¤Ë€± Ž$ø1-áÔ€= $Ÿ= = 50Ôj0Ôj$Ÿ0Ô$Ÿ±²+Ä|$Ÿ$Ÿa¨ÕŸ$øÃYÉj€±€±€½5€Éj€s÷€±€Éj€¤Ë€˜–€g€s÷€Œa€½5€€,€˜–€€,€s÷€áÔ€çïÃ=bñ€7777ÔBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó,0’I$’I$’I)$’I$’I$’m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡*[çÂ2+k€C!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUU@UUUUUUUUUUUUUUUUUUUð `s÷€¤Ë€g€՟YÕŸ€±€áÔ Ž€…˜ïÉñYtPUÌ=b=bI—ÃI—UÌ1-g€$Ÿ= j0Ô= 50ÔUs¤Ë€€,€g€a¨= $Ÿ0Ô0Ô0Ôg€€,€a¨Us$Ÿj$Ÿ+Ä+Ä+Ä| 5 5$Ÿ0Ô$Ÿ$Ÿ$Ÿj$Ÿj0ÔI>s÷€€,€s÷€Œa€€,€g€a¨I>a¨€,€¤Ë€½5€Œa€ÕŸY¤Ë€ô$a¨0Ôa¨UsØŒºŒºtPn6ÕŸ€€,€Œa€s÷€g€€,€½5€çïáÔ€±€€,€g€s÷Y½Žbô$=bn6ô}1†Œº€Œa€= 0Ô$Ÿ= 0ÔI>= I>Us= Usa¨7777ÔBUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@0I$’I$’I$”’I$’I$’I6Ûm¶Ûm¶ÛnI$’I$’I$–Ûm¶Ûm¶ÛmÛm¶Û`‹pd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUAUUUUUUQUUUUUUUð `½5€= = = a¨ÕŸYô$¤Ë€Œa€a¨= 0Ô$Ÿ$Ÿ= I>a¨UsUsg€s÷€g€= I>0Ô0Ô= a¨½5€s÷€˜–€€,€Usj 5jjjjjj0Ô0Ô= = 0Ôj 5+Ä+Ä| 5jjjj 5$Ÿ$Ÿ$Ÿjj0Ô0Ô0Ôj0Ô0Ô= j+Ä+Ä|+Ä| 5+Ä+Ä|+Ä+Ä|jj 5j+Ä| 5$ŸI>$Ÿjj$Ÿ+Ä|jj$Ÿ= I>g€Œa€Éj€áÔ€áÔ€a¨I>0Ô= a¨½51-ô$Éj€s÷€I>a¨Œa€7777ÔBUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓX0$’I$’I$’RI$’I$’I6Ûm¶Ûm¶ÛnI$’I$’I$–Ûm¶Ûm¶ÛmÛ`Š×>”é[\ c¡*[çÂ2+k€C!Lt%sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUTUð `a¨˜–€€,€˜–€¤Ë€¤Ë€áÔn6±YÕøŒº€çï1-Ã1-1-=b1-YŒa€a¨ 5 5+Ä|j 5j= 0Ô= $Ÿ 5$ŸI>˜–UÌ€…À,€UsŒa€Éj€Éj€½5€Éj€çïI—=bn6¥$b ŽáÔ€çïÕŸYáÔ€ÕŸ€½5€s÷€g€Éj€ô$çïçï½5€½5€½5€±€½5€¤Ë€¤Ë€Éj€¤Ë€Usg€Œa€Œa€Éj€±€±€½5€˜–€€,€UsUsUsg€I>a¨€,€€,€€,€€,€½5€çïÉj€a¨7 ú—‚±²|Us±²~±²|$Ÿ7 ‚±²| 5+Ä~±²~7 €¤Ë€ô$Y˜–€$Ÿ±²}s€…€…€7777ÔBUFR&bÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓUUUUUUUUUUUUUUU]ï{Þ÷½ï{Þ÷½ï|ç9Îsœç9Îsœç9Îs½ï{Þ÷½ï{Þ÷½ï{Þ€„!B„!B„!B!B„!B„ ŠS RØ×>”é[\ c¡*[çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUU@UUUUPUUUUU@UUU@PUUð b7 €js÷€s÷€a¨s÷€€,€Œa€˜–€½5€ÕŸYáÔ€¤Ë€g€€,UÌ€,€a¨+Ä|$ŸŒa€˜–€= 0Ôa¨g€Usg€½5€çïçïçïYçï€,€= j±²}ú—ú—ú—€$Ÿg€áÔ€áÔ€çïa¨s÷€Œa€s÷€g€Éj€Éj€Éj€€,€I>ŒaY$ø$øÉj€0Ô±²~±²|0Ôs÷€ç€g€0Ô0Ô0Ô0ÔI>UsUsa¨ÕŸ€…ÉÃ1-áÔ€g€= ±²}ú—ú—ú—€0ÔI>Us€,€UsUs€,€€,€€,€½5€çïäˀçïŒa€±²+Ä}s€…sú—‚±²| 5+Ä+Ä|I>UsUsUsÕŸ€˜–€Éj€7777²|BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@ 0’I$’I$’I)$’I$’I$’m¶Ûm¶Ûm¶ä’I$’I$’Im¶Ûm¶Ûm¶Ý¶Û`‹)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS [çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTTU@UUUUUUUUUUUUPUUUUUUUð `±€€,€¤Ë€Œa€I>Us$Ÿ±²}€…€…€…€ 5j±²~±²}ú—ú—ƒ+Ä+Ä+Ä|j¤Ë€¤Ë€˜–€€,€˜–€Us±²}ú—ú—€…ú—‚±²+Ä~7 €ú—€…s€…ú—‚7 ú—ú—ƒ+Ä|I>s÷€˜–€çïg€s÷€˜–€±€±€±€g€Us$Ÿ 5$Ÿ0Ô$ŸI>$Ÿ$Ÿ0ÔUsa¨g€= 0Ô= €,€˜–€ô$çïY ŽÕŸ€Œa€s÷€I>= a¨€,€€,€s÷€€,€€,€½5€½5€½5€€,€s÷€Us€…‚±²|€,€= Us= 50Ô0ÔjI>I>I>s÷€= 0Ôa¨Œa€áÔ$øYYáÔ1-çïYbI—€,€7777²BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@$0I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶Ûm¶ÐŠ•-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èRØ×>”é[\ c¡*[çÂ2+k€C!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUEUUUUUUUUUUUUUUUUUUUUUUUUUUUð `g€çïUs0Ôj 5 5$Ÿ+Ä|jj= g€a¨€,€a¨Œa€˜–€Œa€±€g€= UsUsI>a¨UsI>0Ô$Ÿ 5j$Ÿ 5Œa€jŒa€¤Ë€˜–€Éj€s÷€I>$Ÿ= $Ÿj0ÔjUsa¨UsI>s÷€Éj€Éj€s÷€ÕŸ€ô$ÕŸ€= 0Ô0Ô= I>a¨0Ô= Usj$Ÿ0Ô0Ôj 50Ô= = 5¤Ë€Œa€g€Œa€€,€Us0Ô 5$Ÿ 5= j= Us$Ÿ0Ô$Ÿj+Ä~7 €…€…ú—‚±²| 5I>a¨s÷€I>= = = $Ÿ0ÔUsa¨a¨0ÔUsa¨½5$ø7777²BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@80I$’I$’I$”’I$’I$’I6Ûm¶Ûm¶ÛnI$’I$’I$–Ûm¶Ûm¶ÛmÛm¶Û`‹pd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS SÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUQUUUUUUUUUUUUUPUUUUUU@UUð a1-=b=b$ø=b1-bäˀ0ÔI>I>$Ÿ0Ô$Ÿa¨$Ÿ$Ÿ$Ÿa¨˜–€s÷€g€I>$Ÿ±²| 5j€,€˜–€˜–€¤Ë€s÷€˜–€g€˜–€Éj€áÔ€Éj€€,€¤Ë€€,€I>a¨¤Ë€s÷€jI>$Ÿ$ŸUss÷€a¨= g€g€՟€¤Ë€I>Us$Ÿj$Ÿ$Ÿ$Ÿs÷€Us˜–€€,€a¨g€a¨s÷€a¨$Ÿ0Ôj$Ÿ0Ôú—‚7 ƒ+Ä|$ŸUsŒa€€,€0ÔÕŸ€±€ÕŸ€g€€,€½5€Éj€±€s÷€s÷€Us€,€˜–€a¨I>j±²|$Ÿ= s÷€s÷€çïg€՟€±ú—ƒ+Ä~±²|0ÔUs= = a¨$Ÿ 57777²BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@P0 $’I$’I$’’I$’I$’I&Ûm¶Ûm¶ÛmÉ$’I$’I$’Ûm¶Ûm¶Ûm»`ŠçÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆٣díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUU@UUUUUUUUUUUEUUU@UUð `$ŸI> 5 5 5+Ä+Ä~±²~7 ú—€ 5= €,€s÷€I>UsUsI>0Ôs÷€a¨±YáÔ€s÷€ÕŸ€çïŒa€= j+Ä}ssú—€I>s÷€s÷€= I>I>Us˜–€˜–€½5€€,€€,€€,€€,€Éj€Éj€¤Ë€= ±²|+Ä| 5s÷€ÉjY€,€0Ô0Ôg€0Ô 5g€= g€ 5ja¨½5€áÔ€çï Ž˜–€¤Ë€Éj€±€˜–€€,€Usj$Ÿ 5+Ä|= = 0Ô= j 5j$Ÿj$Ÿ$Ÿ 5 5$Ÿ±²}ú—‚±²}€…€…‚±²~7 €…s‚7 ú—€…ƒ+Ä~7 ƒ+Ä| 5= $Ÿ0Ô0Ô€,€s÷€s÷€7777²BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@h0$’I$’I$’JI$’I$’I$›m¶Ûm¶Ûm·$’I$’I$’Km¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡*[çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUEUUUUUUUUUUUUUUPUUEUUPUUUUð `áÔ€ÕŸ€€,€Us0Ô+Ä|jj 5j0ÔI>Usg€¤Ë ŽáÔI—Yô$±€I>Uss÷€a¨s÷€˜–€€,€€,€g€a¨= s÷€€,€˜–€˜–€˜–€€,€˜–€áÔ€±€¤Ë€¤Ë€˜–€±€Œa€s÷€€,€˜–€¤Ë€Éj€Usa¨g€Us0Ô 5Usg€0Ôs÷€çïYa¨ 5+Ä+Ä|$Ÿ˜–YI—s÷€= +Ä|+Ä|j= ±²|j0ÔI>Uss÷€$Ÿ+Ä| 5= ÃtPb 5+Ä+Ä}€…‚±²~±²~7 ‚7 ƒ+Ä+Ä|j$Ÿa¨ÕŸ$øÕŸ€I>Usg€՟€±€ô$a¨j+Ä+Ä| 5+Ä|7777²BUFR&bÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓBUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷¼„!B„!B„!„!B„!B„!cÆ1ŒcÆ1ŒcÆ1„!B„!B„!B”¥)JP‹N•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜ê[çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUATDUUUUUUUUUUUUUUUPUUUUUUð b±²+Ä|jjj0Ôg€ 5±²+Ä|Usg€I>±²+Ä~7 ‚±²|a¨0Ô7 €+Ä~±²+Ä~±²+Ä| 5±²|$Ÿa¨˜–€¤Ë€¤Ë€g€I>g€= g€g€a¨I>= 0Ô$Ÿs÷$ø=b$ø1-±€Œa€€,€˜–€áÔ€Éj‚7 ‚±²|$ŸI> 5j= = ±€˜–€= s÷€I>0Ô$Ÿs÷€¤Ë€= UsŒa€ô$$ø¤Ë€Œa€Usa¨ja¨I>= = 5$Ÿ0Ô½5€Œa€= jŒaƒ+Ä|Œa€€,€I>g€I>$ŸUsŒa€I>0ÔI>Œa€g€Œa€€,€Œa€˜–€g€€,€a¨±²|$Ÿ+Ä|= €,€½5€½5€7777²|BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€0I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶Û’I$’I$’I%¶Ûm¶Ûm¶ÐŠ•-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUTPPUUUUTUUUUUUUUUð `g€Œa€s÷€s÷€Œa€€,€g€€,€˜–€Œa€a¨a¨g€a¨€,€= Us$Ÿ0Ô$Ÿa¨g€0Ôj0ÔUs= I>= = = Usa¨ ŽçïI—ÕŸ€€,€Œa‚±²}ss€Œa€…ƒ+Ä}€…€…ƒ+Ä|j 5+Ä}€…ss€…€…€…‚7 ‚7 ƒ+Ä|I>¤Ë€…‚±²|a¨±€g€I> 5I>0ÔUs0ÔjI>a¨I>= j= g€$Ÿj±²}€…€j0Ôjs÷€Éj€Œa€Œa€Œa€½5€Œa€˜–€Éj€s÷€UsÃYáÔ€Œaƒ+Ä|Éj€Éj€s÷€g€€,€˜–€˜–€I>0ÔjjI>a¨$Ÿg€= 0Ô$Ÿ 5€,€½5€±€7777ÔBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€,0 $’I$’I$’’I$’I$’I&Ûm¶Ûm¶ÛmÉ$’I$’I$’Ûm¶Ûm¶Ûm»m¶Û`‹k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸2ÇBT¶5Ï„e:V׆B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUEUUUUUUUTA@U@PUUUQUUð `¤Ë€UsŒa€Éj€¤Ë€±€s÷€±€±€0Ô0Ôj 5 5jjj0Ô$Ÿ0ÔUs±€$Ÿú—€g€½5€ÕŸ€˜–€¤Ë€a¨I>= 0ÔI>$Ÿ0Ô0Ôa¨I>0Ô$ŸI>g€½5€Usg€j$Ÿ$Ÿ0Ô$Ÿ= $ŸUs= jú—€…ú—€…s‚±²|$Ÿ= ±²|a¨+Ä~7 €$Ÿ$Ÿ+Ä+Ä+Ä+Ä|$Ÿ 5$ŸUs= Us+Ä~7 ‚±²~±²|0Ô$Ÿ+Ä+Ä|0Ô€,€s÷€¤Ë€€,€= ±²| 5jja¨s÷€Us0Ô±²|0ÔUs€,€I>$Ÿ+Ä|0Ô= €,YṲˀg€s÷€7777ÔBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€D0$’I$’I$’RI$’I$’I$Ûm¶Ûm¶Ûm¹$’I$’I$’[m¶Ûm¶Ûm·`ŠÆ¹ðŒ§JÚàÈS [çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUEUUUT@UUUUUUUUTUEUUTð `g€Œa€g€a¨g€a¨a¨jI>I>Éj€a¨s÷‚±²|a¨˜–€Œa€a¨a¨s÷€˜–€€,€s÷€a¨I>= j±²| 5 5j+Ä~7 sƒ+Ä+Ä|$Ÿ 5j$Ÿ 5 5+Ä|±²+Ä+Ä~±²}ú—€…‚±²| 50Ôj+Ä}ú—‚±²~±²|= Us$Ÿ0Ô$Ÿ$Ÿjjj$Ÿ$Ÿ0Ô0Ôj 5 50ÔI>a¨±€½5€½5YÉj€€,€çïô$Usa¨Us= +Ä|$Ÿj7 € 5+Ä|jj7 sssú—‚±²+Ä~±²+Ä|j 5$Ÿ= I>0Ô= 5I>Œa€Œa€˜–€jjs€7777ÔBUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€\0’I$’I$’II$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’Im¶Ûm¶ÐŠ2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚàÈS RØ×>”é[\ c¡*[çÂ2+k€C!Lt%Kc\øFS¥mpd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUUUUUPPUUUUUUUUð a€…ƒ+Ä|a¨¤ËY¤Ë€g€0ÔUs 5 5$Ÿ= $Ÿ 5$ŸjjUs¤Ë€I> 5+Ä+Ä| 5 5I>a¨I>= I>UsUsI>= 50Ô$Ÿj$Ÿs÷€Us= 5= ja¨g€˜–€g€= 0Ô 5±²+Ä+Ä~±²+Ä~7 ‚7 ‚7 ‚7 ‚7 ú—ú—€…ss€Œaú—‚±²+Ä|0Ô0Ô$Ÿ+Ä+Ä~±²~7 ‚±²}ú—ú—‚±²~±²+Ä~±²| 5±²}€…sƒ+Ä|0Ô0Ô0Ôjj0ÔUsáÔYçïYáÔ€a¨s÷€a¨½5€±€I>$Ÿ0Ô$Ÿj 5$Ÿ0Ôjj$Ÿa¨Œa€$Ÿ7777ÔBUFR&bÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó‚UUUUUUUUUUUUUUUUUU]ï{Þ÷¾sœç9Îsœç9Îsœç9Þ÷½ï{Þ÷½ï{Þ÷½ï@B„!B„!B„!„!B„!B„!BÆ0‹Êt­® …1Е-sáN•µÀ!¦:¥±®|#)Ò¶¸!¦:¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTPUUUUUUUUUUUUUUUU@UUUUPð `$Ÿa¨YŒa€Us$Ÿ 5+Ä| 5±²~±²~±²}€…ú—ú—ú—€…ú—‚±²~±²~±²}ú—‚7 ƒ+Ä|±²}ú—€…€…‚±²~7 €Us0Ô= $Ÿs÷€¤Ë€çïçïçï½5€ÕŸ€€,€¤Ë€= ¤Ë€€,€¤Ë€s÷€s÷€Œa€€,€I>g€½5€ô$çï±€ô$áÔ€Éj€¤Ë€Éj ŽÕŸ€áÔ€Éj€áÔ€€,€Œa€a¨0Ô$Ÿ 5I>g€a¨Us˜–€Œa€Œa€Usg€I>a¨€,€g€UsUs€,€€,€±€ 5ú—‚7 ‚7 €…‚7 €I>˜–€ÕŸ€ÕŸ€±€Œa€€,€s÷€˜–€€,€a¨a¨$Ÿjj$Ÿj+Ä~±²|7777²|BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀ0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUU@UPUUUUUUUUUTUUUð c+Ä| 5Usa¨€,€a¨= Usa¨a¨a¨Us€,€s÷€I> 5 5= I>g€$Ÿj0Ô 50Ô$ŸI>s÷€a¨Œa€g€s÷€Œa€a¨a¨€,€g€UsUsI>UsI>I>€,€g€g€j 5 5$Ÿú—€…€…‚±²}ú—ú—‚7 ‚7 ‚±²+Ä|$Ÿ= I>€,€˜–€= ±²~7 €€,€Éj€çï¤Ë€0Ô= = I>0Ô= $Ÿ 5$Ÿ 5j$Ÿ±€a¨¤Ë€±€Œa€= €,€˜–€a¨˜–€˜–€€,€I>Us0Ô 5jUs0Ô0Ô$Ÿ7 ƒ+Ä|I>Usj= Us0Ô0Ôj$ŸI>s÷€Œa€g€Us7777Ÿ€BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀ$0’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶àж5Ï„e:V×D2ÇsáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUU@UUUEUUUUUUTU@Pð `I>= $Ÿj= I>0ÔUsg€՟=báÔYÃçïô$€,€Œa€˜–€Us 5j$Ÿ+Ä|$Ÿ±²| 5+Ä+Ä}€…‚±²}€…‚±²+Ä| 5I>I>$Ÿ 5j0Ô$Ÿ$ŸjI>= 5+Ä|jI>a¨g€g€¤Ë€çï€,€Œa€a¨s÷€€,€s÷€g€= j0Ô 5$Ÿ 5jjs÷€= ja¨±²|Usj$Ÿ±²~±²}€…ú—ú—‚7 ú—sss€…s€…ú—‚±²~7 ú—s€Œa€…ssú—‚±²+Ä| 5 5+Ä~7 ‚7 ‚±²~±²}ú—‚±²~7 ú—‚7 ‚7 ‚±²| 5+Ä}ú—€7777Ÿ€BUFRöbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀ<@3334DDDDDDDDDDDEUUUUUUUUUUUVfffffffffffgwwwwwwwpŠ …1Е-sáN•µÀ …1ÑÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUPUUUUPUUUUPUUTUUUUUUUUð b±²~7 ú—ƒ+Ä|Usa¨0Ô= ±²~7 ƒ+Ä+Ä|+Ä+Ä~±²|jjjú—€…‚7 €j= Usa¨Œa€½5€¤Ë€ÕŸYô$±€¤Ë€g€= ±²+Ä+Ä|j0Ô= I>$Ÿ0Ôa¨= 0ÔI>a¨s÷€˜–€Œa€½5€Éj€Usg€UsŒa€ 5+Ä+Ä}ss‚7 €+Ä|j0Ô 50Ô$Ÿa¨Usa¨Usa¨Œa€Éj€I>$Ÿ+Ä}ú—ƒ+Ä}€…‚±²~±²|= I>€,€Œa€˜–€€,€= 0Ô 5jI>a¨˜–€±€Éj€çï½5€ô$½5€¤Ë€s÷€= 0Ôa¨g€g€€,€= j 5s÷€½5€½5€a¨s÷€7777€€BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀX0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­® …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUTUð `I>= jj$ŸUsô$ç€a¨= 0ÔUsUss÷€a¨Usa¨a¨UsŒa€Œa€¤Ë€€,€±€€,€0Ôg€a¨= ±€˜–€$Ÿ 5jj$ŸUs= j$Ÿ 5 5 5$ŸUsI>0Ô€,€¤Ë€çïs÷€0Ô7 s€O€Œa‚7 €jI>Us= $Ÿ$Ÿj0Ô= Uss÷€I>$Ÿg€€,€UsI>= ¤Ë€¤Ë€g€a¨s÷€a¨s÷€g€I>j0ÔI>= 0Ô0Ôg€$Ÿ€,€Us˜–€±€½5€€,€I>= = j 5±²+Ä~7 ƒ+Ä~±²~7 ‚±²~±²~7 ú—‚7 ‚7 ‚7 ú—‚7 ‚±²| 5˜–€€,€Us½5€77775€BUFR&bÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÂUUUUUUUU]ï{Þ÷½ï{Þ÷½ï{Þ÷Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½ï½ï{Þ÷½ï{Þ÷½ï{ÞðB„!BŠ …1Е-sáN•µÀ …1ж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUU@UUUUUUUUUQUUUUUUUUUUUUð `0Ôg€j$Ÿ€,€˜–€s÷€I>$Ÿ$ŸUs= 0Ô= €,€Œa€g€$ŸI>+Ä~7 €…ú—‚7 ú—€Us€,€Œa€s÷€s÷€a¨g€Œa€€,€¤Ë€s÷€g€0Ô 5 5UsI> 5I>0Ô±²~7 €I>= Usa¨s÷€a¨Usa¨= Us˜–€¤Ë€g€= a¨I>UsUsj+Ä|j 5$ŸUsŒa€s÷€€,€½5€Œa€a¨s÷€g€I>g€0ÔUsUs= 0Ôj7 ‚±²|±²+Ä+Ä|jI>Œa€€,€g€Usg€€,€˜–€a¨g€s÷€I>$Ÿs÷€a¨= 5Us= I>0ÔI>g€s÷€±€s÷€= 0Ôj7777²|BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðETUUUPUUUUUQPUUUT@UUUU@UUUð `±²|0Ô 5+Ä|UsŒa€Éj€€,€I>€,€Œa€UsI>s÷€s÷€g€j 57 ‚±²+Ä~±²~7 ‚±²~±²~7 ‚7 ƒ+Ä|= ½5Y ŽáÔ€Œa€g€= 0ԤˀŒa€ÕŸ€çïÃÉj€Œa€€,€$ŸI> 57 €$Ÿ0Ô+Ä~±²~±²}ú—sss€…ƒ+Ä|I>g€j0Ô 5j 5= s÷€I> 5€,€$Ÿ+Ä|+Ä~7 ‚7 ‚±²~±²|0ÔÉj€½5€a¨¤Ë€Éj€½5€Us˜–€g€g€Éj€˜–€I>UsI>0Ô0Ôj±²~7 ‚±²~7 ú—€€,€ô$çïô$Y¤Ë€s÷€€,€s÷€Éj€Œa€s÷€= 7777÷€BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Û¶Û`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V׈S c\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUTUUUUU@UTUUUUQUUPUTUUUUUð `Usa¨¤Ë€Éj€±€€,€0Ô7 ƒ+Ä|$Ÿ€,€˜–€çï$ø= 5g€0ÔÉj€ô$Y=b˜ï¥$¥$¥$‚1†=»½Ž±Y¥$ ŽI>7 ƒ+Ä+Ä|$ŸI>Œa€½5Ãg€I>+Ä~±²+Ä+Ä|áÔÃÃô$áÔbU̽5€Us˜–€˜–€çï¤Ë€= Us 5j0Ô+Ä| 5$Ÿ0Ôg€0Ô= 0ÔUss÷€$Ÿ 5±²~7 ú—‚±²|0ÔI>I>I>= +Ä~7 € 5I>a¨Usj±²~±²|+Ä}ú—ss€O€O‚7 €$ŸI>Us½5€±€Œa€s÷€g€s÷€s÷€I>a¨YÉj$ø½5€€,€I>I>j= g€˜–€7777÷€BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó40I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUU@T@T@UUUð `Œa€€,€a¨0Ô= $Ÿ$Ÿjj= 0Ô$ŸUsŒa€UsI>= 0ÔI>˜–€˜–€½5€€,€I>g€I>0Ô$Ÿ$Ÿ0ÔI>a¨0Ô 57 ‚±²+Ä|7 €$Ÿ¤Ë€¤Ë€Œa€€,€s÷€Éj€ô$ÕŸ€I>$Ÿ= $Ÿ0Ôa¨0Ô+Ä+Ä~±²|0Ô€,€ 57 ‚±²~±²~±²~±²}ú—‚7 ƒ+Ä|j+Ä+Ä}sú—€…ú—‚7 ‚7 €…‚±²~±²|j$Ÿ±²~7 €…€…€Œa€…€±²~±²+Ä}ssssssú—sú—ƒ+Ä|a¨s÷‚±²+Ä~±²~7 ‚7 ƒ+Ä|0Ôa¨g ŽÃ Ž¤Ë€= g€UsUs0Ô0Ô7777÷€BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓH0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUQUTPETQ@QQUUð `±€¤Ë€s÷€0Ô$Ÿ0ÔŒa€Us+Ä|Œa€˜–€˜–€˜–€Œa€¤Ë€€,€I>jjjj 5$Ÿ= $ŸjjUs= g€½5€çïô$çïô$áÔ€çïÕŸ€áÔYÕŸ€a¨a¨0Ô0Ô0Ô= 0Ô0ÔI>Œa€¤Ë€ÕŸ=b$øI>½5€¤Ë€0Ô= = Uss÷€0Ôjj+Ä|j 5j$ŸjUs0Ô+Ä}ú—€…‚7 ú—€…ú—€$Ÿ$Ÿ+Ä+Ä|+Ä|jj 5 5±²| 5+Ä|±²}ú—sú—‚±²|= 0Ô0Ô 5+Ä|$Ÿj 5+Ä|0Ôj 5 50Ô= $Ÿ7777÷€BUFRæbÿ« fÓ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó\0I$’I$’I$’’I$’I$’I&Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÛmÛm¶Û`‹pC!Lt%Kc\øFS¥mpd)Ž„©lkŸÊt­®!¦:¶5Ï„e:V×D2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðU@T@QPUUPUUUUUUð `$Ÿ$Ÿj$Ÿ7 €…s€…ss€…ss€…€Œa€Œa€…ss€…ƒ+Ä|j7 €…€Œa€Œa€Œass€…€…ss‚7 ú—ú—ú—€…s‚7 ú—€…ƒ+Ä}ú—‚±²}€…sss€Œaú—€$Ÿ0Ô0Ô±²| 5+Ä+Ä}ú—€ 5+Ä|j 5 5+Ä~7 €…s€Œas€…€…ƒ+Ä|$ŸUsUsjú—€+Ä| 5I>€,€€,€$Ÿjú—ú—s€O€Œa€Œa‚7 € 5ja¨a¨$Ÿj= = $Ÿ 5 50Ô0Ô0Ô$Ÿ$Ÿ$Ÿ0Ôj 5+Ä|0Ôa¨€,€g€s÷€UsUs7777÷€BUFR&bÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓUUUUUUUUUUUUUUUUU^sœç9Îsœï{Þ÷½ï{Þ÷½ï{Þ÷½÷½ï{Þ÷½ï{Þ÷½ï{ÞB„!B„!B„!„!B„!B„ ŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUUUUUUT@PUUUUUUUUUUUUUUUUUð `Us= I>s÷€= j$Ÿ= a¨s÷€˜–€¤Ë€a¨ 5±²~±²|g€€,€jUsI>¤Ë€I> 5jj$Ÿ= Us€, Ž ŽÉj€çïçï½5€˜–€a¨$Ÿ= +Ä|±²~±²~±²| 57 ƒ+Ä+Ä|0ÔUsŒa€€,€˜–€Œa€0Ô±²}ú—ƒ+Ä|j= ¤Ë€±€a¨g€s÷€Œa€a¨a¨= s÷€Us€,€˜–€˜–€s÷€±€çïô$Yçï½5€ÕŸ€Œa€¤Ë€±€±€ÕŸ€¤Ë€Œa€s÷€0Ô0Ô= ¤Ë€±€˜–€˜–€±€˜–€½5€˜–€˜–€˜–€Us= I>a¨g€€,€Œa€¤Ë€±€¤Ë€±€½5€±€a¨€,€±€s÷€˜–€±Y7777²|BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@ 0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUAUUDUUUUUUUUUUUUUTUUUUUUUð aÃ=b$ø Ž˜–€˜–€½5€¤Ë€±€ÕŸ€ô$=b=bô$a¨j7 ‚7 €j$Ÿs÷YI>j 5 5$Ÿ+Ä|ú—ƒ+Ä|= g€a¨Usg€a¨= s÷€½5I—1-Y¥$b$øŒº1-áÔ€ô$±€Us$Ÿa¨Œa€€,€±€¤Ë€UsI>€,€a¨$Ÿ 5a¨0Ôj0Ôs÷€Us€,€áÔ€ô$±€½5€˜–€˜–€Œa€a¨UsŒa€0ÔI> 5 5 5j+Ä+Ä|0ÔUsáÔ€½5€áÔ€$Ÿ 5$Ÿ$Ÿjja¨¤Ë€½5€˜–€a¨$Ÿ 5±²|Us±Ãô$˜–€I>€,€˜–€±€g€= jj0Ô7777 BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@$0$’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠB˜éRØ×>”é[\ c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUQUUUUUUUUUUUUUQUUUUUUUUUUUPUUð `I>Œa€¤Ë€½5€j$Ÿ+Ä|$Ÿ= UsUsI>Us$Ÿ$Ÿ0Ô0Ôg€jŒa‚7 ú—‚7 ‚7 €˜–€±€g€Us€,€€,€€,€UsUsUs˜–€a¨g€՟Ã Ž ŽYÉj€€,€Œa€€,€˜–€a¨½5$ø ŽáÔ€¤Ë€±€ÕŸ€ô$±€ÕŸ€áÔ€ô$YáÔ€¤Ë€$Ÿ+Ä|7 €$Ÿs÷€Éj€çïý5€€,€g€0Ô$Ÿ˜–€Œa€Œa€s÷€s÷€±€çïô$s÷€€,€g€= = UsŒa€¤Ë€ÕŸ€Éj€Éj€€,€g€Us= ¤Ë€€,€0Ôa¨g€s÷€˜–€±€˜–€s÷Ãa¨0Ôg€$Ÿ±²+Ä|jI>= ˜–€a¨a¨= = 7777 BUFRÆbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@80 $’I$’I$’RI$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$–Ûm¶Ûm¶Ûm»`ŠçÂ2+k€" c¡*[çÂ2+k€" c¡*|#)Ò¶¸!¦:¥±®|#)Ò¶¸D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ `= OX€s÷€OX€¤Ë€…tP˜ï€…1-ô$I—Ã1-YI—h±Y˜ï€…1-½5€½5€˜–Yg€çïÛºô}±²‚V%1†1†ô}ô}èH½Ž˜ïtP˜ï¥$Ü%Q²Y ŽY¥$‚€Þ‚‚ô}¥$tPtP€…[æ$øI—€…ÕøÉÀçïY˜–€€,€€,€g€= Ï…g€¤Ë‚V%[ætPÉÃU̱€˜–€Ï…çïYYUÌ=bÃŒa€OX€$ŸOX€s÷€½5€0Ôj 5[€Ï…±€±€Œa€OX€OX€0Ô= g€½5€¤Ë€s÷€Œa€s÷€ 5[€= $ŸI>jI>çïYUÌ[æÃ1-Ûº[€[€7777jBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@P0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇB–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUPQ@UUUUUUUUUTUUUUUUUUUUUUUð `I>½5€¤Ë€áÔ€Éj€¤Ë€I>UsI>Us0Ô$Ÿj0Ô$ŸI>j$Ÿ= I>j$Ÿ+Ä+Ä|I> 5+Ä|j$Ÿ±²~±²+Ä|$Ÿg€I>a¨= 0ÔgÂn6áÔ€ÕŸ€±€¤Ë€€,€I>0Ô 5= $Ÿ0Ô€,€±€s÷€€,€g€I>Us= s÷€€,€€,€s÷€g€UsUsjj 5 5+Ä}ú—‚±²|0Ô€,€¤Ë€Œa€I>s÷€= I>I>s÷€g€a¨¤Ë€ÕŸ€±€ÕŸ€s÷€I>Éj€Éj€¤Ë€çïáÔ€çï ŽYçïçïçïg€Usg€Œa€ÕŸ€½5€±Œº€…n6b=bçïô$Y1-à ŽYUÌUÌUÌô$¤Ë€±€7777 BUFRæbÿ« fÓ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó@d0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUEUUPEUUUUUUUUUUTUUUUð `±€g€±€áÔ€áÔU̱YîbÉÃîbîb¥$€…UÌUÌ=b$ø1-=b=bn6bI—1-½5€ÕŸ$øô$ÃÃ1-1-ô$Œa€= s÷€€,€s÷€˜–€Œa€½5€½5€ÕŸ€çï½5€¤Ë€a¨ 5$Ÿ+Ä|j= = $ŸI>I>I>= a¨$Ÿ 5+Ä~±²|j+Ä|$Ÿa¨g€Us= Us= 0Ôj= = €,€çï=bÃ$øYô$ÕŸ€áÔ€Éj€ÕŸ€Éj€çï Ž$øÕŸ€±€€,€a¨s÷€¤Ë€Éj€¤Ë1-$øÃ$øYÉj€s÷€Us 5+Ä| 5I>áÔ€Éj€±€±€½5€€,€€,€s÷€a¨s÷€¤Ë€g€s÷€g€7777 BUFR&bÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓBUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU^÷½B„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œc!B„!B„!B„)JP‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUU@UUUUPU@ð `s÷€a¨0Ô0Ô= g€g€I>Us¤Ë€ô$ô$ç€= I> 5jj$Ÿj0ÔI>Œa€áÔ€ÕŸ€±€I>= 0Ô0ÔUsa¨¤Ë€Éj€ÕŸ€½5€çïáÔ€áÔ€áÔ€I>Us= Us˜–€ô$n6I—1- Žçï±€½5€Œa€±€ÕŸY Ž$øÃçïô$áÔ€ÕŸ€½5€Œa€a¨UsŒa€g€¤Ë€Éj€g€= = ±²~7 ú—‚7 ‚7 €$ŸI>I>= j0Ôa¨= UsI>= = = Œa€±€s÷€€,€0Ô= $Ÿ+Ä}ú—ú—‚±²|$ŸUs±²|ú—‚7 ú—‚7 ƒ+Ä~7 € 5€,€±€±²|= g€g€€…ú—‚±²|7777²|BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€0$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚå1ж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUU@UUUUUUUUUUDUUUU@UUUUUUUUUð `= g€Œa€¤Ë€€,€g€I>0Ô$Ÿ= I>˜–€Us0ÔUs 5+Ä+Ä~7 €€,€˜–€¤Ë€g€UsUs= g€s÷€˜–€€,€±€±€˜–€Œa€a¨I>˜–ÃÃáÔ€ÕŸ€çïÃYŒa€a¨a¨I>= = = I>= $Ÿjj$Ÿú—€7 ú—‚7 €0Ô±€ÕŸ€±€g€a¨0Ô$Ÿ$Ÿ= Uss÷€I>j= Œa€Usj±²}ú—‚7 ‚±²~±²~±²|s÷€½5€Œa€UsUsa¨UsI>UsI>€,€¤Ë€ÕŸ€ô$YÕŸ€ô$Y1-$øÃÃ$øô$Yô$çïçï½5€€,€I>I>Œa€€,€g€Œa=b7777BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€,0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUPUPUUUUUUUUUUUUUUUUUUUUUUUð a$øÉj€¤Ë€= j 5 50Ô0Ô= ±²~±²}ú—ú—‚7 ‚7 ‚7 ƒ+Ä|jj0Ôa¨0Ô 5j 5±²~7 ‚7 ƒ+Ä| 5g€€,€s÷€a¨UsUs= = = 0Ô€,€±€¤Ë€¤Ë€˜–€Œa€½5€˜–€Œa€g€g€g€g€s÷€Œa€¤Ë€g€a¨Us= = $Ÿ$ŸI>s÷€˜–€€,€Œa€¤Ë€Œa€€,€Us= I>0Ô0Ô= a¨˜–€˜–€€,€g€UsI>Us= I>Us˜–€±€€,€s÷€g€s÷€Œa€$Ÿ0Ô 5j$Ÿ= €,€½5€ô$ÕŸ€I>= $Ÿ= = 0Ô= Us½5€s÷€s÷€a¨Us0Ô$Ÿ= = 0Ô7777BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€D0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×ÈS [Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUAUUPPUUUUUUUUUUUUUð `0Ôa¨±€±€±€ÕŸ€¤Ë€$Ÿ$Ÿ 5= $ŸI>€,€¤Ë€¤Ë€Œa€¤Ë€±€˜–€s÷€= 5±²+Ä|js÷€€,€g€jj 5+Ä+Ä|jj= I>I>Œa€s÷€g€€,€j+Ä~±²}€…sƒ+Ä~±²|7 ƒ+Ä~7 ú—‚7 ‚7 ‚7 ú—‚7 ‚±²+Ä|0Ô$Ÿ0Ô+Ä~7 €…€…€…‚±²|s÷€Éj Ž Ž˜–€€,€g€€,€s÷€˜–€½5€ÕŸ=bUÌ=bÃY Žô$½5€Éj€½5€ÕŸ€Éj€çï1-€…½ŽtPà Ž$øY1-I—çïô$UÌtPbô$€,€= $Ÿ= = €,€ÕŸ€ô$çïÕŸ€±€I>Us7777BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó€X0 $’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛmÉ$’I$’I$’Ûm¶Ûm¶Ûm·`ŠçÂ2+k€d)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸΕµÀ …:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUQUUUUUUUUUUUUUUUUUTUUUUUUUUUUð `g€g€˜–€˜–€I>Éj€áÔ€Œa€Us= +Ä| 50ÔgÂYçïçï€,€jI>ja¨s÷€a¨±$ø$øÃY=bI—=bbYáÔ€ÕŸ€ô$ÕŸ€Éj€çïYYçïáÔ€˜–€ÕŸ€¤Ë€ÉjÃ=b=bn6=bYô$ Žçï ŽáÔ€çïçï±€€,€¤Ë€±€g€g€UsUs0Ô$Ÿja¨a¨$Ÿ0Ôg€a¨g€Œa€$Ÿ0Ô±²+Ä|$Ÿ 50Ôj 5 5 5= s÷€˜– Ž$øI—1-I—I—1-1-$øáÔ€çïÉj€ô$=bŒº€…€ÕŸ€ÕŸ€ÕŸY=bYn6Õø‚ çîbîbÕø±Y€…I—1-7777BUFR&bÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó‚UUUUUUUUU]ï{Þ÷½ï{Þ÷½ï{ÞùÎsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½÷½ï{Þ÷½ï{Þ÷½ï{ÞB„!BŠ!¦:¥±®|#)Ò¶¸!ÇBT¶5Ï„e:V×FB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUQUUUUUUUUTUUUU@ð aÃçïYô$YI—n6UÌ1- Ž$ø$øÃ1-btPtP1-1-$øÕŸ€½5€g€= = $Ÿ$ŸUsçï=b ޱ$ø1-$øçïUÌn6€…Õø ŽÉj€½5€€,€I> 5±²|±²|jÉj€áÔYçïÉj€¤Ë€€,€Uss÷€€,€áÔ€±€s÷€I> 5jj±²~7 ‚7 ‚7 ‚±²~±²| 5I>g€€,€˜–€s÷€¤Ë€Éj€Éj€áÔ€ô$Éj€ÕŸ€áÔ€±€áÔ€ô$ÕŸ€€,€0Ô$Ÿ+Ä~±²|0Ô˜–€¤Ë€€,€˜–€€,€€,€UsI>g€Éj€ô$ Ž1- Žô$áÔ€˜–€ 57 ‚7 €…€…ss€…ƒ+Ä| 5€,€Us7777²|BUFRbÿ« fÓ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!²LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀPB„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œd„!B„!F1ŒcÆ1ŒcÆ1ŒcÊR”¥ ŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ˜×>”é[\ c\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUU@UUUUUUUAUUUUUUð `$ŸjUsáÔ€±ÃáÔ€Éj€˜–€Œa€s÷€$Ÿ$Ÿ$Ÿ$Ÿ0Ô0Ô= I>€,€Œa€= $Ÿj 5jI>€,€Œa€Éjb1-ô$=b$øÕŸ€Éj€ÕŸ€áÔ€½5€±€±€Éj€Éj€¤Ë€±€çï±€áÔ€ÕŸ€±€Éj€áÔ€ÕŸ€½5€Œa€a¨s÷€$Ÿ0Ô±²+Ä~7 ƒ+Ä|Usg€Œa€±€€,€˜–€€,€½5€áÔ€ÕŸ ŽYYçïYÉj€½5€˜–€I>$Ÿ$ŸjI>s÷€±€Éj€€,€Œa€¤Ë€$Ÿ+Ä}ú—ss€$Ÿ+Ä~±²|j= g€Us= a¨˜–€g€€,€Éj€áÔ€ô$áÔ€€,€s÷€Œa€s÷€Us= = = j0Ô= s÷€7777€…BUFRÆbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!rLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÀP0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@,@ `s÷€6î€C#€6î€6î€[€OX€€,€ÛºÏ…·ž±g€Œa€€,€g€C#€C#€g€˜–€Œa€ž±s÷€€,€ž±Ûº Ž[æ˜ïhtPO±+ ŽÃ Žô$ ŽÃô$Ï…ž±€,€€,€Œa€OX€6î€C#€OX€C#€OX€OX€C#€OX€s÷€€,€ž±˜–€˜–€˜–€ž±ªæªæž±€,€g€[€g€[€C#€6î€6î€C#€[€g€€,€s÷€€,€s÷€€,€ž±Œa€Œa€€,€Œa€Œa€ž±·Ï…··ªæŒa€g€€,€˜–€Ï…[æ+‚ÏÞ·tÃÏ…Ï…[æ¥$O±ÃÃÛºÃP˜–€€,€Œa€6î€j[€€,€Œa€ªæž±OX€g€Œa€·7777–€BUFR&bÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓÂU\cÆ1Œg9Îsœç9Îsœç9Öµ­kZÖµ­kZÖµ­kZÞ÷½ï{Þ÷½ï{Þ÷½ï{ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷ ŠøFS¥mp˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†C RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUU@UUUUUUUUUýàa$ø Ž$øäˀUs= jîb€€,€$Ÿ±1-Ûº±€ô$[€I>0Ô˜–€˜–=b=bYb1-$øÛºÛº€,€Œa€½5€±€Éj€½5YI— Žçï Ž ŽÛº$øbI—hI—$ø Ž=bYÃçïÛº˜–€½5€ô$Éj$øhhbb ޽5€Éj€ÛºYÃçïÛº€,€¤Ë€Us= $Ÿ¥}~¥}~¥}~¥}|ú>îbîb‚+k‚+k‚¥}~+k‚¥}|0Ôg€±Y½5ÃÉj€ô$˜–€çï¤Ë€0Ôg€€,€= s÷€€,€Us€,€Us[€$ŸI>I>Us= €,€ÕŸ€˜–€s÷€s÷€g€Us$Ÿ$Ÿ 57777²|BUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS SçÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUTUUUUUUUUUU@ð ` 5$Ÿg€Œa€¤Ë€I>s÷€I>UsUsI>$ŸUs€,€€,€˜–€€,€a¨0Ô$Ÿ±²+Ä~±²~±²| 5$ŸI>s÷€˜–€˜–€€,€¤Ë€¤Ë€¤Ë€¤Ë€±€Œa€Œa€Œa€Œa€€,€s÷€€,€€,€s÷€s÷€€,€Œa€Œa€±€Éj€Éj€½5€˜–€Œa€Œa€s÷€Œa€Œa€€,€¤Ë€s÷€g€I>= 57 €…€…ú—€Œasƒ+Ä|Usg€€,€s÷€I>I>g€a¨a¨0Ô$Ÿ0Ôjú—ú—‚7 s‚±²~±²| 50Ô½5€çïáÔ€Éj€a¨UsáÔ$ø1-YÃô$$øI—YçïYçï½5€Éj€±€¤Ë€¤Ë€Œa€= j0Ô±²+Ä~7 €7777sBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQUU@UUUUUUUUUUUUUUUUUUUUUUUUUð c+Ä~±²~7 €$Ÿ7 €0ÔjI>j+Ä|0Ô$ŸUss÷€ÕŸ€Éj€çï$Ÿ7 €…€…‚±²|a¨½5€ô$ÃY±€çï±€˜–€a¨= a¨= s÷€¤Ë€±€Éj€ô$ô$¤Ë€a¨a¨g€˜–€áÔYÕŸ€Éj€áÔ€ô$çïÕŸ€¤Ë€€,€Usa¨Usa¨˜–€€,€¤Ë€áÔ€½5€½5€±€½5€ÕŸ€Éj€çïô$YçïçïçïY1-b1-Éj€¤Ë€Œa€¤Ë€¤ËYUÌ¥$tPý5 ŽÃ Ž$øÃ Ž ŽYYáÔ€áÔ€çï½5€±€¤Ë€a¨g€I>0Ô±€ô$$øn6€…UÌ1- Ž ŽYáÔ€±€ÕŸ Ž$ø7777sBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ó,0 $’I$’I$’RI$’I$’I$›m¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm·m¶Û`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€"1Е-sáN•µÀ …1Е-sáN•µÀ …1Е1®|#)Ò¶¸!¦:Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUTUUUTQUUUUUUUUUUUUUUUð a$øUÌ=b$ø1-çïÕŸ€±€±€±€çïáÔYçï±€±€áÔ€ô$ô$áÔ€Éj€±€Usg€Us7 ‚±²|Œa‚±²~7 €$ŸUs0ÔI>a¨I>= Us0Ôj 5jI> 5ú—ss€O€Os€Os‚±²~7 ‚±²+Ä|±²|j±²| 5 5±²| 5Œa€€,€˜–€Œa€€,€s÷€s÷€Uss÷€½5€ô$1-b$øáÔ€ÕŸ€áÔ Ž=b1-$ø=bbŒº€…±YŒº=bÃô$ ŽÃYáÔ$ø1-I—ô$áÔ€áÔYçïÃà ŽYô$ÕŸ€çïáÔ€ÕŸ€ÕŸ€½5€Éj€Éj€½5€ô$YUÌUÌ7777sBUFRæbÿ« fÓ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓD0’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶Ûm¶ÐŠ¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUTUUU@UUUð a=bÃÃÃ$ø=b=b=bUÌI—=b1-=b=b1-Ã$ø Ž Ž ŽáÔ€çï1-ô$YÃYÃ Ž ŽI—1-UÌ$ø$øI—YYçïçï ŽÉj€½5€½5€±€áÔ€áÔY Ž Ž Ž Ž$øI— ŽÃYô$ ŽçïÕŸ€±€±€Œa€€,€€,€Œa€Œa€½5€ÕŸ€Éj€±€Éj€Œa€0Ô€,€¤Ë€€,€Us+Ä~±²|7 ‚±²~7 s‚7 ú—€…‚±²}ú—‚7 ‚±²~±²+Ä| 5$Ÿ$Ÿ$Ÿ= I>I>s÷€Œa€0ÔI>0Ô 5$Ÿ+Ä~±²~±²~±²}ú—‚7 €˜–€ÕŸ€çïçïáÔ Ž Ž$ø$ø$ø1-Ã7777sBUFRæbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓX0’I$’I$’I%$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹)Ò¶¸!¦:¥±®|#)Ò¶¸!”ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUEUUUUUQUUUUPUUUUUUUUð a Žô$I—$ø1-YçïÕŸ€Éj€I>a¨$Ÿ¤Ë€áÔ1-=bYáÔ€çïÃçïô$ô$ô$¤Ë€€,€€,€€,€Œa€a¨= +Ä|Uss÷€½5€Éj€€,€a¨Usg€Usg€˜–€Éj€çï¤Ë€˜–€0Ô$Ÿj$ŸŒa€€,€ú—€…‚±²|0ÔŒa€s÷ƒ+Ä|$Ÿ$ŸI>g€Œa€g€Usjg€¤Ë€˜–€g€€,€UsUs0Ô$Ÿ$Ÿ±²+Ä|I> 5$ŸI>UsUsa¨Us$Ÿ0Ô0Ôj+Ä| 5a¨g‚7 ‚7 ú—‚±²}ss€ 5a¨g€€,€˜–€g€s÷€ÕŸ€áÔ€½5€s÷€áÔbn6UÌbI—1-Y½5€Œa€= 7777sBUFRfbÿ« fÓ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÓUUUUUUUUTD»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»°]ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½ï½ï{Þ÷½ï{Þ÷½ï{ÞðB„!BŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V׆B˜èJ˜×>”é[\ÈS RØÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðDAUUUUUUUUUUUUUUUUUUUU@TUUð `j+Ä|+Ä|$Ÿú—ƒ+Ä| 5+Ä|0Ô0Ô 5j= j$Ÿj 5 5jI>˜–€½5€áÔ€Éj$ø=btPI—Ãô$ÕŸ€ÕŸ€çïYY Žô$ô$YY Ž$ø=b$øÃYáÔ€çïáÔÃUÌI—1-ÃY ŽçïçïáÔ€ô$ô$Yô$ô$ô$ô$çï Ž$øYY Ž$ø$øUÌU̘ïb1-Ãô$=bô$±€€,€UsUs0Ôj±²}ú—‚±²~±²|s÷€çïÕŸ€Œa€$Ÿ±²~7 ‚7 ‚7 ‚±²| 5j±²~7 ú—€…€…€…ú—€…ú—€$Ÿ0Ô[€UsUsg€Us7777BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@0$’I$’I$’JI$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I-¶Ûm¶Ûm¶ÐŠ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS SçÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUPUUUUUUUUUUUUUUUUUUUUUTð `0Ô[€[€[€€,€UsUsg€s÷€Œa€€,€Œa€s÷€s÷€g€I>Usg€½5€±€±€±€±€Œa€˜–€€,€˜–€½5€¤Ë€˜–€˜–€¤Ë€¤Ë€€,€g€$Ÿj 5±²~7 € 5g€s÷€¤Ë€¤Ë€¤Ë€€,€g€Uss÷€½5YY$øçïÛºÛºçïÉj€€,€[€I>Uss÷€˜–€€,€±€ÛºÉj€ÕŸ€ÛºÛºçïYÃÛº½5€ô$ÛºÉj€Œa€s÷€˜–€s÷€I>0Ô 5Us0ÔŒa$øäˀ$Ÿ 5$Ÿ€,€˜–€€,€˜–€Éj=bUÌ1-YÛº˜–€$Ÿj$ŸI>€,€˜–€ÕŸ€Éj€Éj€½5€€,€g€˜–€€,€g€g€Us$Ÿ 5+Ä|7777UsBUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@0 $’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶ÛvÛm¶Û`‹k€C!Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„Â2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUU@TU@UUU@Uð aú—ú—s€…€…s€…‚7 ƒ+Ä~±²+Ä|Uss÷€Œa€˜–€ÕŸ€çïçïÃYY Ž ŽÉj€s÷€˜–€Œa€Œa€€,€$ŸÉj€Éj Ž1-€,€s÷€UsI>I>UsÉj€ÕŸ€ô$¤ËÃ Ž¤Ë€s÷€Œa€0Ôs÷€UsUsI>$Ÿ[€±€¤Ë€Ûº±€˜–€½5€±€ÕŸ€çï½5€€,€Us€,€= g€I>= 7 ‚7 ƒ+Ä| 5 5 5€…€Œas€…‚±²}ú—‚±²|±²|j±€I>Us0Ô±²+Ä+Ä}s€0Ôú—€Œa€ 5Us¤ËYô$ Žçïçï1-$øÕŸ€±€0Ô7 €…€…€…€…€7 €…€$Ÿ0Ôj7777UsBUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@40 $’I$’I$’RI$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUUUTUUUUUUUUUUUð `jI>Us˜–€˜–€I>0Ôjjsss‚7 ƒ+Ä|UsÛºhUÌçïô$¤Ë$øI—h1-Ãçï½5€˜–€s÷€ŒaY±€€,€0ÔI>= = I>[$øhh=b$øYÛº˜–€€,€Œa€€,€½5€Us¤Ë€€,‚7 ‚7 €…s€Œas‚±²|jUsI>Usg€0ÔI>Us[€¤Ë€±€±€±€½5€s÷€I>= $Ÿj 5±²|€,€s÷Y1-=bÉj€Ûº½5€g€g€g€g€Uss÷€g€[€Usg€g€g€±€˜–€˜–€s÷€ô$Y=b ŽÉj€Œa€[€[€[€Œa€˜–Y¤Ë€çïçï¤Ë€UsUss÷€7777UsBUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@L0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@UUT@UUUPUUUUUUUUUUUUUUUUPð ` 57 €Œa€O€Œas€…€0ÔUsUs[€s÷€s÷€[€€,€0Ô= I> 5+Ä| 57 €…€…s€Œas€…ú—€…€$ŸŒa€ô$ÕŸ€Éj€Ûºô$çïYçïYÃô$Éj€g€$Ÿ+Ä~±²}€…€…€…€Œaú—‚±²|UsÉj Ž$øçïÉj€±€¤Ë€½5€Ûº ŽYY ŽYY=b½5ÃUs$Ÿ$Ÿ0ÔI>¤Ë€Éj€ô$$øYçïÃô$ÕŸ Ž=b$ø$øÕŸÃÕŸ1-ô$±€½5€s÷€[€ 5Us˜–€Éj€çï½5€±€Éj€ÕŸ€¤Ë€Œa€±€ÕŸ€±€±€¤Ë€Éj€s÷€Us 5±²+Ä+Ä+Ä|= s÷€7777UsBUFRöbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!¢LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@`@"""""""""""#33335UUUUffffffffffffwwwwwwwwwwpŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„¾”é[\ÈS RØ×>”é[\ÈS RØ×>”èÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUTUU@ð `[€½5€g€UsUs0Ôj$Ÿ½5€¤Ë€€,€s÷€s÷€Œa€±€±€€,€Éj€±€Œa€g€I>g€՟€çïçïÛºÛº[€I>= ±$ø=b=b$ø ŽÃI—ÃÛº˜–€€,€€,€˜–€±€¤Ë€ÕŸ€ÕŸ€ÕŸ€±€˜–€¤Ë€Éj€çïô$ Ž$øô$ÛºÕŸ€ÛºÛº±€I>= s÷€g€= 0Ôs÷€ô$[æUÌŒa€Éj$ø1-¥$h$øÕŸ€Œa€¤Ë ŽÛº˜–€çï½5 ŽI—tPŒº1-ô$Ã1-Ã$øÕŸ€ô$Éj€±€±€½5€Éj€Éj€Œa€½5€±€€,ƒ+Ä~7 ú—€j[€g€s÷€g€€,€˜–€s÷€0Ô 5±²}€…€…€7777²}BUFR&bÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔBUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU_{ÀB„!B„!B„"„!B„!B„!CÆ1ŒcÆ1ŒcÆ1Œd!B„!B„!B…)JP‹[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTUUUUTUUUUUUUU@UUUUUð as€…€…ú—€= ˜–€I>ú—ú—ƒ+Ä~±²~7 ‚7 ‚±²| 5g€Œa€s÷€$ŸUss÷€[‚±²+Ä}€…€…€…sss‚±²|½5€ÕŸ€ô$YÛºI>g€±€ÕŸ€g€Us±€±€¤Ë€±€¤Ë€g€= I>±²~7 ‚7 ‚7 ‚±²+Ä|jUsUsUs€,€€,€= I>[€s÷€˜–€½5€Œa€g€Us0Ô$Ÿ±²~7 ‚7 ‚7 €j0Ô[€€,€= I>€,€I>= I>$Ÿ€,€I>= 0Ô 5±²}ú—ú—‚7 s€…€0Ôg€€,€Œa€ô$$øY Žô$çïÛºçï Ž ŽÃÛºÉj ŽÛº= 5+Ä}ú—‚±²|[€77775BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô€0$’I$’I$’RI$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$–Ûm¶Ûm¶ÐŠS RØ×>”é[\Êc¡*[çÂ2+k€C!Е-sáN•µÀ …1Е-sáN•µÀ …1ж5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðEUUU@D@UUUUUUUUUUUUUUUUð `Us+Ä|¤ËU̘tPI—ÛºYÃhU̱=b=bÕŸƒ+Ä}ú—ú—‚7 ‚7 €Œasú—€= 0Ô+Ä+Ä| 5±²|+Ä| 5+Ä+Ä}€…‚7 ú—s€Œass€Œas€…ú—ss‚7 ú—‚±²|j 5 5Us= $Ÿ 5= ¤Ë€˜–€½5€€,€¤Ë€Œa€ÕŸYô$Yô$ô$Ûº¤Ë€ç€ÉjUÌ½Ž½Ž¥$Œº[æ=bçï±€Éj€ô$±€[à ŽÃŒa€Œa€¤Ë€˜–€Œa€I>[€g€I>I>0Ôj±²}€…‚7 ú—ú—‚7 ƒ+Ä|€, Ž=bI—ÃÕŸ€çïÛºçïà ŽÃ Ž7777YBUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô€,0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUQUUUUUUUUUUUð `çïŒa€[€j+Ä|= $ŸjUsŒa€UsUs€,€˜–€Éj€ÕŸ€ÕŸ€Éj€ÛºçïY Žçï Ž ŽY Ž Žô$ÛºÕŸ€Éj€ÕŸ€Ûº½5€½5€Éj€ÕŸ€ÕŸYÉj€±€Éj€Éj€ô$Y=bÃYÛºçï±€Œa€½5€Éj€±€˜–€€,€¤Ë€½5€ÕŸ€ÕŸ€ÛºÛºÉj€ÕŸ€çïô$ô$Yçïô$1-=b ŽYÕŸ€Éj€g€= $Ÿ 5+Ä| 5 5j$Ÿj$ŸI>±€Éj€˜–€½5€¤Ë€±€ÕŸ€Éj€Œa€[€[€€,€¤Ë€½5€Éj€ÕŸY1-=bhŒºUÌÕŸ€½5€ÕŸ$ø1-I—hhhI—I—ÃÃô$Y7777YBUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô€D0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUTUUUUUEUUUUUUUUUUPATð `çïÛº½5€ÕŸ€ô$à ޽5€ÕŸ€Ûº½5€çïÃ$øÕŸ€Ûº˜–€s÷€€,€˜–€ÕŸ€½5€Éj€½5€˜–€˜–€½5ÃI—I—I—1-$øÛº¤Ë€ÛºÛº1-UÌ[æI—äˀ€,€I>0Ô 5±²+Ä+Ä|s÷ ŽUÌçïI>0Ô$Ÿ 5$Ÿj= ¤Ë€€,€Œa€Usg€s÷€g€Usj= 0Ô±²|0Ôs÷Y$ø¤Ë€j 5 5j 5Us0Ô= I>Us= I>= g€¤Ë€s÷€s÷€g€±€ÕŸ€¤Ë€±€½5€±€˜–€s÷€[€s÷€Œa€€,€Us0Ôj0Ô= = 5 5+Ä+Ä|+Ä+Ä|$Ÿg€Usj+Ä|7777YBUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô€X0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ÆÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUAUUUUUUUUUUUUUUUUUUUUUUUUUUUUýàc| 5 5jI>OX€OX€OX€[€= $Ÿ 5¥}|0Ô½5€0ÔI> ŽI—ÃÉj€½5€˜–€±€ÛºÃ$ø=bI—€…€…[æ[æYÏ…€…¥$h=b=b=b=bh€… ŽY Ž1-ô$ Žô$Ûº$øÉj€¤Ë€€,€½5 Ž[æ€s÷€¤Ë€s÷€OX€s÷€ÉjO±1-Ûº±€±€g€˜–€Ï…Ï…tPO±tPÃô$1- ޱ€±€¤Ë€g€ÉjÃI—h$øçï½5€¤Ë€Œa€±€ô$ Ž1-€…[æ1-[æ€Ï…g€g€OX€I>0Ô$ŸOX€I>g€υۺ½5€Éj€Éj€Ï…Éj€˜–€ô$1-€…[æÃI—7777YBUFR&bÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô‚UUUUUUUUUUUUUUUUUUU]k{Þ÷½ï{Þ÷½ï{Þ÷½ïœç9Îsœç9Îsœç9Îp!B„!B„!B„B„!B„!B„!cÆ0‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUU@UUUUUUUUUUUUUUUUUUUUUð aÃÉj€½5€±€g€s÷€$ŸI>[€½5€çïçï½5€Éj€ÛºÕŸ€Éj€ÕŸ€ÕŸ€ô$çï¤Ë€¤Ë€€,€Œa€Éj€g€çïÉj€Œa€s÷€€,€Œa€˜–€Œa€Us+Ä~±²}ú—‚7 € 5 5$ŸI>Y€…h€…hI—I—UÌÃ=bUÌtP±Yâ-èHÕøØ–€˜–€ÛºÃ±Y¥$‚ ç²èH çht‚V%1†èHâ-èHèHâ-â-‚V%ht€…[ætP=btP€…=b½Ž‚%Q1†ô}Õø˜ïñ€çïÛº½5€Œa€Éj˜ïŒºtPh1-1-±€ÕŸ1-I—tP±YtPYÕŸ€ô$ÕŸ€˜–€ÛºŒa€½5€Œa€çï½5€77775BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÀ0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’Km¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡lkŸÊt­®ˆd)Ž„©lkžÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUEUUUUUUð `ÛºÃI—I—ÃY$ø$øÃ1-I—Œº€…±Y¥$hhI—I—Ã$ø1- ŽÛº ŽÃtPI—$ø±€ÛºÉjY1- Ž Ž¥$½ŽŒºtP€…tPhh[æ1-½5€Œa€ÕŸYYçïÕŸ€çï±€±€˜–€Œa€Éj€¤ËÃà ŽÛº½5€½5€[€UsUsI> 5$Ÿ[€€,€s÷€¤Ë€g€= s÷€g€s÷€s÷€±€Éj€ÛºÃY±€€,€I>= 5+Ä|0Ô±h˜ï€ÕŸ€Œa€s÷€½5€ÕŸ€ô$À…˜ï€çï½5€±€I>+Ä}ú—ƒ+Ä~7 ú—€s÷1-=bŒa€I>I>[€[€0Ôj7777-BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÀ$0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶Ð‹Êt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUPUUUUUUUUUUUUUUUUUUUUUUUUU@Tð `$Ÿ[€g€I>j= 0ÔI>±²~±²~7 €[€˜–€Éj€Éj€g€= ¤Ë€s÷€[€ô$çï€,€[€s÷€˜–€€,€€,€Œa€s÷€g€0Ô 5 50Ô= s÷€€,€g€[€I>[€€,€€,€[€Œa€¤Ë€˜–€g€[€s÷€[€0Ôjj 5 5+Ä+Ä|$ŸUs˜–€¤Ë€¤Ë€¤Ë€±€ÕŸ€ÛºÛºÛºYYô$çïçïÛº½5€ÛºÛºÕŸ€½5€ÛºÉj€¤Ë€±Y Ž˜–€[€j= 5€,€¤Ë€½5$øÉj€€,€g€UsŒa€Us[€[€g€0Ôj0ÔI>0Ô 50Ôj$Ÿ= ±²+Ä+Ä|gƒ+Ä|7777-BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÀ<0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUð b±²}ú—€…€…‚±²|I>˜–€Éj€Œa€˜–€±€Éj€½5€Éj€Éj€±€˜–€½5€Œa€I>0Ô$ŸI> 5+Ä|j 5j$Ÿ[€½5€±€±€Œa€˜–€I>€,€Œa€¤Ë€½5€ô$YÉj€s÷€€,€Œa€s÷€¤Ë€€,€s÷€I>s÷€€,Ãçï ޽5€s÷€¤Ë€Œa€s÷€[€s÷€€,€çïh±Yâ-èHâ-½ŽÕøÉÃtPhI—±$ø[æ=bô$ô$çïÕŸ€¤Ë€Éj€Œa€¤Ë€€,€½5€Œa€[€0Ô˜–€Us˜–€g€g€gƒ+Ä~±²|j[€€,€[€= 5±²~±²+Ä|j 5 5[€UsI>jg€$Ÿs÷€Œa€0Ô 57 €…‚±²|s÷€7777-BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÀP0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lk¡N•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUUUUUUUUUUUUUUUUUð b7 ‚7 ƒ+Ä~±²~7 ‚7 s€…€…€…‚7 ‚7 €…‚7 ú—ú—€…‚7 s€…€Œas€…ú—s€…€Œas€…s€…sú—‚7 ú—ú—€ 5= 7 ú—ƒ+Ä~7 ‚±²+Ä~±²| 50Ôg€Œa€€,€s÷€Œa€g€UsUsI>g€¤Ë€€,€Œa€s÷€0ÔUsg€= j$Ÿ= €,€±€çï±€ÕŸ€s÷€±€¤Ë€s÷€s÷€±€½5€Ûº½5€€,€I>0Ô0Ôj 5$Ÿ$Ÿg€±€Ûºçï±€½5€˜–€˜–€¤Ë€¤Ë€½5€ÕŸ€ô$çï$øUÌ€…˜ï€…=b1-Yg€Œa€ÛºÃñ€½5€€,€I>s÷€[€I>s÷€7777-BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÀd0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm»`‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-te:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUTUUUUUUUUUUUUTð `±€çïô$ ŽçïÕŸ€ô$Œa€€,€s÷€g€Œa€˜–€Éj$ø=b=bYçïô$ÕŸ€çïÛºYÃ1-ÛºÕŸ€ÕŸ€¤Ë€˜–€€,€±€½5€Œa€I>[€s÷€˜–€Ûºô$½5€€,€€,€€,€±€¤Ë€±€±€¤Ë€çïçïI—1-Ãô$ÕŸ€s÷€g€€,€I>= $Ÿg€s÷€Us+Ä+Ä|j 50Ô0ÔUs½5€çïô$1-à Žô$çïÉj€ÛºY[潎˜ïèHÃŒa€= $Ÿ= €,€s÷€½5€ô$ÃYçï±€€,€jjj€,€çï Žçï½5€±€g€0Ô$Ÿj 50Ô0Ô7 €…s€…s€7777-BUFR&bÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÂUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷½ï{ÞðB„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1Œc!B„!@Š2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V׆B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUAUUUUAQUUU@QUUð a€…‚±²| 5€,€Œa€Œa€Œa€g€g€I>I> 5 5 5= [€= 0ÔI>jI>s÷€˜–€˜–€˜–€˜–€˜–€±€çïçïs÷€Us[€Œa€g€ 50Ô= jj$Ÿj 5+Ä+Ä|0Ôú—‚±²+Ä|˜–€ÛºÕŸ€¤Ë€˜–€g€g€Us= [€g€[€½5€g€½5€¤Ë€s÷€j+Ä+Ä|j$Ÿ+Ä|j$Ÿ[€Œa€s÷€= 0Ôj[€= Œa€˜–€g€0Ô±²}ú—ú—€…ss€Œas€…€…ú—€…€Œaú—‚7 €…€€…‚±²~±²~±²~±²|$Ÿ[€[‚±²|j+Ä}€…s€…€g€±€ÕŸYŒa€s÷€0Ô$Ÿ77775BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô0$’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èKçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðQTUUUUUUUUUUUUUUUUUUUUUUEUUUUð `$Ÿj+Ä|= = = j+Ä~±²~7 ‚7 ‚±²}€…€…s€…‚7 €I>Œa€= jg€Éj€±€€,€€,€Éj€ÕŸ€Ûº€,€€,€¤Ë€˜–€Œa€[€$Ÿ= I>±€ÛºÉj€g€Œa€Éj€˜–€€,€s÷€Œa€Œa€Ûº ŽÛº˜–€¤Ë€I>I>Œa€$Ÿ0ÔI>j= g€ۺÃÕŸ€˜–€Œa€s÷€[€[€g€g€s÷€˜–€[€Uss÷€€,€˜–€[€s÷€Œa ŽÃ Žô$$ø[æ=bg€I>$Ÿ 5 5= = Us[€Œa€g€[€= 0Ô= $Ÿ0Ô 5±²|0Ôjj0Ôjjj 5 5$Ÿ 5j˜–€g€7777²~BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô(0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðEUUTUUUUUUUUUUUUUUUUUUUUUUUUUUUð `€,ƒ+Ä|0Ô[€s÷€Usg€€,€g€½5€ 5j+Ä|j 5= 0Ô[€±€ô$ÛºŒa€s÷€I>I>[€€,€Œa€½5€ÛºÛºg€+Ä|7 ƒ+Ä|j 5 5= j0Ô0Ô 5 5j0Ô0Ô 5jŒaYÉj€€,€±€¤Ë€½5€±€€,€0Ô[€Œa€= I>ç‚â-˜ï[æI—=bYçïY1-=b±€g€= s÷€I>[€I>g€€,€€,€Us€,€s÷€Us€,€Us= = €,€$Ÿ0Ԥˀ˜–€¤Ë€˜–€g€0Ô= [€I>= ˜–€˜–Y±€ÛºÕŸ€Œa€˜–€s÷ Ž[€$Ÿ0Ô[€7777²~BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’Im¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUU@UUUUUUUUUUUUUUTUUð `ÛºŒº˜ïI—ô$ÛºÉj€˜–€UsI>YI—ô$ ޱ€Œa€½5€€,€€,€Œa€Us0Ô= = ¤Ë€s÷€Éj€€,€g€0Ô$Ÿ= = $Ÿ 5ç€I> 5±²~7 ‚±²}ú—€…s€…ú—‚7 ‚7 € 5$Ÿ0Ôs÷€j$Ÿ= I>0Ô0Ô0Ôjj= ±€0Ô$Ÿ[€½5€±€ÕŸ€çïŒa€= g€I>[€[€Us€,€s÷€Usg€s÷€€,€˜–€˜–€= Œa€s÷€Œa€¤Ë€˜– Ž Ž$øÛº€,€¤Ë€€,€[€˜–€g€s÷€€,€[€Œa€0Ô 5+Ä+Ä}ú—€+Ä~7 ƒ+Ä| 5I>s÷€€,€g€g€= Uss÷€g€7777²~BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔT0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUPUUUUUUUð `g€s÷€¤Ë€= ˜–€˜–€s÷€0ÔUs= Éj€Ûº¤Ë€€,€½5€çï½5€½5€g€[€$Ÿ$ŸI>0ÔI>I>0Ô€,€Ûº Ž ŽÛº¤Ë€s÷€s÷€çïY1-[æ[æ¥$UÌÛºÉj€±€I>= Us= [€Usg€ۺ€…½Ž€…UÌÉj=b1-$øYÛºô$=bŒº€çïUs0Ô= 0ÔI>[€j 5jI>Éj€g€$Ÿ0Ô˜–€= I>s÷€¤Ë€Éj€Éj€Ûº=bI—Œa€ 5+Ä~±²~±²~7 ‚±²~7 € 5j 5jjjj$ŸI>s÷€ÕŸ$ø$øY¤Ë€½5€€,€€,€˜–€˜–€ç Ž¤Ë€I>UsI>7777²~BUFR&bÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔUUUUUUU\ëZÖµ­kZÖµ­kZÖµ­o{Þ÷½ï{Þ÷½ï{Þ÷½óœç9Îsœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{Þ€!B‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUUUUUUUUUUUUUUUUUUUUUUð `[€ 5+Ä~7 ú—€= çï ŽçïÛºYô$1-Ã1-çïà ŽÛº¤Ë€s÷€= +Ä}ú—€…€…ú—€…ƒ+Ä|0Ô€,€Œa€€,€€,€g€$Ÿ= [€g€Œa€Œa€I>$Ÿ$Ÿ 5ú—€…€…€…€…€…€js÷€Œa€¤Ë€½5€½5€¤Ë€½5€½5€Éj€ô$Yô$Éj€¤Ë€Œa€±€±€Œa€0Ô 50Ô 5= ¤Ë€½5€ÛºÛº½5€¤Ë€¤Ë€€,€[€s÷€Œa€s÷€= I>$Ÿjj$Ÿj0Ôjj±²|j0Ôg€s÷€g€s÷€g€Us= s÷€Us= 0Ô$Ÿ0Ô0Ô[€±€ÕŸ€ÕŸ€¤Ë€s÷€±€¤Ë€±€g€Œa€77775BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶ÐŠt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%KcáN•µÀ …1Е-sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUQQUUUUUUUUUUUUUUUUUUUUUUUð `s÷€j 5$Ÿj= j$Ÿs÷€˜–€çï[€UsUsI>0Ô0Ô0Ô$Ÿ0Ô€,€j$Ÿ$Ÿ= I>g€I>j+Ä| 5 5±²| 5Us¤ËYUÌ1-Ãs÷€€,€˜–€I>$Ÿ0ÔŒa€˜–=bÕŸ€ÕŸ1-çïÉj€ÕŸYçïÕŸ ŽØ–€Us$Ÿ˜–€s÷€[€js÷Y ŽÉj€±€˜–€Œa€˜–€UsñÃUÌ€…€…=bI—€,€˜–€½5€˜–€s÷€½5€ô$Éj€±€Éj€˜–€Éj€Éj€Éj€˜–€s÷€Œa€g€ÉjY=bUÌô$YÛºÉj€ô$Éj€Éj€ÕŸ$øI—½5€[€g€[€g€€,€½5€ÛºÛº7777 BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUQUUUUUUEUUUUUUUUUTUUUUTPUUU@ð `±€±€Ûº€,€[€$Ÿ= jj±²|$Ÿj= g€Œa€Œa€˜–€g€[€g€g€g€[€Usg€s÷€[€[€= 0ÔI>0Ô 5$Ÿ+Ä| 5+Ä| 5= g€Us±€I>I>[€g€g€0ÔUs$Ÿ0Ô[€Us0Ô 5jg€±€ÕŸ€ÕŸ€ÛºÛº½5€½5€g€[€I>˜–€±€0Ô$Ÿ[€s÷YY$øÉj€±€Us+Ä|j[€s÷€±€ÕŸ€ÕŸ€çïÉj€½5€¤Ë€½5€Éj€ÕŸ€Éj€½5Ã1-1-½5‚7 €$Ÿú—ú—‚±²|g€Œa€s÷€s÷€Us[€Us[€Us½5€Œa€s÷€€,€[€€,€0Ô+Ä}ú—‚±²|7777 BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@40’I$’I$’I%$’I$’I$’I¶Ûm¶Ûm¶ÛnI$’I$’I$’Ûm¶ÐЦ:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:TÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUQUEUUUUUUUUUð `$Ÿj$Ÿ˜–1-tP$øô$½5€±€±€˜–€s÷€˜–€±€Éj€±€€,€ô$[æ€çïô$Ûºçï¤Ë€€,€€,€[€¤Ë€Ûºg€s÷€±€Œa€˜–€Œa€[€[€s÷€±€Éj€Ûº ŽÛºÛºÉj€¤Ë€Éj€½5€˜–€˜–€Œa ŽÛºs÷€= $ŸI>$ŸUs$Ÿ 5$ŸI>Œa€±€ÛºI—[æ=b$øçï¤Ë€€,€Œa€ÕŸYŒa€ 5j 5+Ä| 5$Ÿ0Ô0Ô$Ÿ+Ä|I>ÕŸ=b[€ŒaÃ$øô$$ø ŽUÌ€…[æ€Ûº€,€[€[€[€jI>g€= I>I>s÷€s÷€Œa€˜–€ÕŸ€çïÉj€˜–€ÛºÉj=bI—˜–€I>7777 BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@H0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUQUUUUUUUUUUPEð `= €,€g€I>= s÷€Us$Ÿ0ÔUsUsI>I>0Ô½5€ÛºÃ Žô$ç€Us= jj$Ÿ$Ÿj= g€$ŸjjI>= [€s÷€½5€˜–€s÷€Éj€½5€€,€Œa€Œa€€,€Œa€s÷€I>$ŸUsg€˜–€g€s÷€€,€Us= = 0Ô$Ÿ$Ÿ$Ÿ 5±²|= €,€±€€,€ 5±²|˜–€çï$Ÿ= = $Ÿ+Ä| 5 5Usg€Uss÷€g€I>I>¤Ë€½5€= 0ÔI>= 5j$Ÿj$Ÿ 5jjjs÷€g€½5€ô$YÛº±€Éj€±€[€7 ú—‚7 ƒ+Ä~±²~7 €±²| 57777 BUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@\0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUU@UAU@U@UUUUUUð `j= €,€Œa€I> 5$ŸYI—=b$ø Ž ŽYÛº˜–€€,€Us[€g€Œa€€,€[€jUs€,€˜–€s÷€I>= €,€[€€,€çïYYY˜–€Œa€€,€€,€s÷€I>g€g€€,€s÷€j 5±²+Ä~±²}€…€…ƒ+Ä~7 ú—‚±²~±²|j$Ÿ0ÔI>0Ô 5±²~7 €±²+Ä|j= $Ÿ0ÔjUsssss‚7 €I>= s÷€$Ÿ 5+Ä~±²~±²+Ä|+Ä+Ä+Ä| 5= ±²}ú—‚7 ú—ú—ƒ+Ä|jUs= jj= s÷€g€Us[€g€g€Usg€= Uss÷€UsI>= 0Ô7777 BUFR&bÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔBUUUUUUUUUUUUUU^sœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½ï½ï{Þ÷½ï{Þ÷½ï{ÞðB„!B„!D!B„!B„ Š2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇD#)Ò¶¸!¦:¥±®|"Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUTU@UUUUPUPUUUUð `0Ô 5j= = I>€,€€,€¤Ë€€,€= [€= $Ÿ€,€0Ô0Ô€,€I>Us[€Us¤Ë€˜–€$Ÿj$Ÿj+Ä}ú—‚±²}ú—‚±²~7 ‚7 ú—ú—€…‚±²~7 €j$ŸI>€,€Œa€ÕŸ€çïçïÛºÉj€s÷€¤Ë€s÷€ 5 5 5±²+Ä|= jI>s÷€±€˜–€Œa€= €…€Œasú—€…€…€ 50ÔI>$Ÿ= $Ÿ$Ÿ½5€ô$ô$½5€½5€s÷€Œa€Œa€±€Ûºg€ 5±²+Ä+Ä+Ä|jUs˜–€UsUs0Ô$Ÿ+Ä}ú—€…‚±²| 5+Ä|Us½5€Œa€±€¤Ë€Éj€Œa€UsÉj€˜–€˜–€Ûºô$çï1-1-77775BUFR&bÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô‚UUUU P„!B„!B„!D!B„!B„!B†1ŒcÆ1ŒcÆ1ŒcÈB„!B„!B„! R”¥)K{Þ÷½ï{Þ÷¾1€‹)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¥±®|#)Ò¶¸!¦:¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUATUTTUUUUUUUUUUUPUUUð a ŽçïÕŸ€Ûºs÷€= 50Ô 5I>Us[€[€I>0Ôj$Ÿ+Ä+Ä|= +Ä|j= Œa€Œa€I>±²}ú—€Œa€…‚±²+Ä~±²~±²|+Ä| 5 5$Ÿ$Ÿ±²~±²+Ä|= g€$Ÿ$Ÿj 5+Ä|$Ÿ[€0Ô+Ä}€…sú—ú—ú—ú—‚±²~±²|$Ÿ= Us[€s÷ ŽŒa€ÕŸ€$ŸŒa€±€Œa€±€€,€½5€¤Ë€s÷€€,€UsI>j$Ÿj0Ô$Ÿ0Ô$Ÿs÷€ÛºÕŸ€½5€0Ôs÷€Œa€[€ 5$Ÿ$Ÿg€Us$Ÿ0Ôj7 ‚±²|$Ÿ= jUsg€€,€g€0Ô0ÔI>s÷€77775BUFR&bÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÂUU]kZÖµ­kZÖµ­kZÖ÷½ï{Þ÷½ï{Þ÷½ï{ß9Îsœç9Îsœç9Îsœç{Þ÷½ï{Þ÷½ï{Þ÷½ï½ï{Þ÷½ï{Þ÷½ï{ÞðŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUPUUUUUUUUUUUUUUUUUU@ð `g€I>I>= [€= UsI>j0Ô0Ô[€g€Éj€˜–€½5€çï±€¤Ë€ÛºÉj€0Ôj 5±²|j$ŸUsI>j 5 5j0ÔI>s÷€€,€[€s÷€±€Œaú—€…sss‚7 €j0ÔUs= g€½5€Œa€= = $ŸI>[€±€Ûº¤ËY€…I—s÷€0Ôg€˜–€ÕŸ€s÷€[€s÷€[€[€[€Us 5j= = 5 50Ô0Ôj= [€˜–€˜–€Éj€Œa€Œa€¤Ë€€,€g€g€g€€,€€,€[€€,€˜–€Us0ÔÉj€Us= Uss÷€s÷€g€€,€çïU̽5€ô$s÷€[€j€…€Œa€…€Os€…s€77775BUFRbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÂLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð„ „!B„!B€B„!@€! !B!B„!B„!aèHô$èHn6ô$n6n6bZbZŸc“†þŸctþbZzzô$èHèHŸcg€g€gƒ“†ÿ“†þbZtþbZèH“†ÿtüg€˜–ƒtþbZèHô$zzô$n6tü±Ã[æ€ô$±€˜–€ÃPÏ…Ûº€,€Œa ŽtPé Ž$øŒa€Œa‚ŸcbZbZbZ¤Ë€½5€±€ÛºÃPs÷€gƒtüg‚bZ“†üçü¤Ë€Œa€g‚ŸcŸcbZèHzô$ô$zn6èHtÿtýèHgƒtþbZèHn6n6n6“†ü€,€ô$˜ï$øŒa‚bZn6èH¤Ë€€, Ž ŽYçïۺۺυ¤Ë€½5€¤Ë€±€˜–€½5€ÃPŒa€s÷€7777sBUFRbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÂLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶9ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðB„!B„! B„!B„!B„„!B„!B„!B„!B„!`ÃPçïô$[怅tPO±C|à ŽÛºçïô$±€€,€˜–€˜–ƒ“†þŸcŸc“†ÿtýèHèHŸctþbZbZbZtþbZn6ô$ô$ô$n6n6n6èHn6n6n6n6n6bZ“†üs÷ƒ“†þbZèHbZn6n6ô$ô$n6bZ±O±=b1-1-[æ=bô$ÃP˜–€€,€ŒaÃ$ø[æ=bY1-¤Ë€s÷€gÂèHèHŸcztüs÷€s÷€€,€½5€±€ô$ÛºÛº¤Ë€±€˜–€˜–Y€,½Ž¥$[æ1-YÃ$øY Ž1-1-=bô$Ï…½5ƒtü€,€Œa€Œa€¤Ë€Œa€˜–€¤Ë€gƒ“†þŸctþŸcn6z7777sBUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô00$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶ÐŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðPUUUUUUUUUPUUUUUUUUUUUUUUUTUUð `Œaú—€ 5$Ÿ$Ÿ 5±²}€…€Usjg€Œa€½5€€,€ÛºÉj€Œa€çï½5€½5€¤Ë€±€€,€˜–€s÷€g€g€s÷€[€s÷€I>Usg€½5Y=bÃ$ø$øô$Éj€[€s÷€Us 5±²}ú—€…€0ÔUsI>Us[€Œa€[€ 5$Ÿ= 0Ô$Ÿ$Ÿ[€= I>¤Ë Ž=bçï[€˜–€s÷€g€€,€Us0Ô+Ä|±²|$Ÿ$Ÿ 50Ô$Ÿ$Ÿs÷€s÷€Us€,€s÷€s÷€I>UsI>Uss÷€s÷€[€= j0Ô$Ÿ= I>€,€g€˜–€˜–€€,€¤Ë€¤Ë€g€˜–€±€€,€ 5$Ÿú—€= s÷€±€½5€s÷€[€Usg€7777€ŒBUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔD0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÐŠÆ¹ðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUTTUUTUUUUU@UQUUUUUTð `I>= Œa€½5€±€Œa€€,€½5 ŽÛº$Ÿ±²~7 ssss‚±²|$ŸI>0Ôj 5+Ä|0Ôj 5= Us0Ô[€I>g€Œa€Us±²+Ä| 5+Ä|$Ÿs÷€[€Usg€ 50Ô$Ÿ€…ú—‚7 ‚±²}€…s€[€€,€Œa€˜–€s÷€0Ô$Ÿ0Ô 5$Ÿ 50Ô0Ô 5ú—ƒ+Ä~±²|UsI>$Ÿ= = Us±²|jI>Œa€Œa€Œa€[€= $Ÿ0Ô$Ÿ$Ÿ 5±²|+Ä}ú—sú—€…€…ú—‚7 €[€[€s÷€˜–€ÕŸ€ÛºÛºÉj€¤Ë€s÷€I>0Ô 5ú—ss€…s€…€…s€Œa€…€Œas€…€7777€ŒBUFRæbÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔX0$’I$’I$’II$’I$’I$“m¶Ûm¶Ûm¶Ü’I$’I$’I%¶Ûm¶Ûm¶ÛnÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èRØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUPUAUUUQUUUUUð asú—‚7 ú—‚7 €…€…€Œas€…‚±²|j0ÔUsUs$ŸI>[€0Ô 5[€g€s÷€ÛºÕŸ€ÕŸ€¤Ë€€,€Usg€$ŸUss÷€s÷€±€Éj€[€= 0Ôj0ÔŒa€Us 5$Ÿ$ŸI> 50Ô[€g€€,€€,€˜–€Éj€˜–€˜–€I>= 0Ôj$Ÿ0Ô= [€= = = 0Ô= Usj±²}€…ss€…€ 5= Us[€= 5+Ä+Ä|$Ÿj0Ô0Ô$ŸI>ô$ÕŸ€Œa€s÷€Us0Ô$Ÿ$Ÿ+Ä|0Ô0Ô0ÔI>I>0ÔUs 5 5±²| 5jI>½5€ÛºÕŸ€s÷€€,€¤Ë€¤Ë€¤Ë€€,€˜–€7777€ŒBUFR&bÿ« fÔ2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔUUUUUUUUU]ï{Þ÷½ï{Þ÷½ï|ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þ÷¾÷½ï{Þ÷½ï{Þ÷½ï{ÀB„!BŠS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS RØ×>”é[\ÈS*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUQUUU@PQUUUUUUUUUUUUUUUð `€,€s÷€g€= $Ÿ 5j0Ô0Ôj+Ä| 5+Ä|I>Éj$øÃô$ÛºÛºÕŸ€Éj€¤Ë€€,€[€I>= I>0Ô+Ä~7 ‚±²|ú—€…€…‚7 ‚±²+Ä~±²+Ä|ú—‚±²}s€Œas€…ú—€…€…ú—‚7 ƒ+Ä~7 ú—‚7 ‚7 ‚±²+Ä|$Ÿ= = +Ä|Us 5€,€˜–€˜–€€,€[€[€I>0Ô0Ô0Ô0ÔI>UsUs¤Ë€ÛºÃI—hUÌYÛº¤Ë€¤Ë€±€Éj€Ûº$øI—[€UsI>Usg€s÷€€,€€,€Œa€˜–=b±Y˜ïh€çïÛº€,€g€ 5Us±€çïçïUs0ÔI>s÷€I>77775BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2*Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUTQTUUTTTTð `= = UsŒa€Ûº±Y±Y½Ž˜ï€ÕŸUÌ$øYÕŸ€ÕŸY$øI—$øÕŸ€g€˜–€Us[€s÷€j0ÔUs1-=bÃtP[æ ŽÛºÉj€Éj€Éj€±€Éj€Éj€Éj€0ÔUs0Ô0ÔI>j$Ÿj$Ÿj= ±€ÕŸÃÛº¤Ë€Uss÷€g€g€I>= $Ÿ 5 57 ú—€Œas€…€…ú—€…‚7 €$Ÿ+Ä|$Ÿ 5 5 5+Ä}ú—‚7 ƒ+Ä|= s÷€s÷€[€I>Us 5$Ÿ0Ôj0ÔI>+Ä~7 ú—‚7 €…€Œa€O€Œa€Œa€Œa€Œa€…€Us= $Ÿ+Ä~7 ‚7 ‚±²~±²| 5 5+Ä| 5ú—€7777–BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`‹k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðTU@UUUUUUUUUUUUUUTUUð b7 ú—ú—€…s€…ú—€jUsI> 5±²+Ä~±²~±²~7 ƒ+Ä+Ä+Ä+Ä| 5 5jI>$Ÿ±²}s€Œass‚7 €jI>$Ÿ 5$Ÿ$Ÿ 5 5 5 5 5I>€,€UsI>[€g€¤Ë€½5€±€˜–€˜–€¤Ë€±€½5€çï=bÕŸI—I—tP€çïY Žçïô$1-çï½5€Usj= g€g€[€0Ô€,€s÷€€,€I>$Ÿ0Ô+Ä|$Ÿ 50ÔŒa€€,€€,€= Us±²~7 €…ú—sú—‚7 €…€…ú—€…s€…‚7 s‚±²}ú—€ 5 5Us[€Us0Ô0Ô+Ä|±²~±²+Ä}s‚7 €j7777–BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@40 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUEUUTUQUE@UUUUUUUUUUQEUUUUUUUTð `±€±€g€= 5±²| 5$Ÿ$ŸUss÷€s÷€Œa€½5€g€€,€s÷€I>$Ÿ7 ƒ+Ä~±²|0ÔUsg€Us0Ô0Ôj+Ä| 5 5$Ÿj 5$Ÿ+Ä| 5Us 5€…€Œass€…ú—€$Ÿs÷€g€s÷€[€[€[€Us[€g€s÷€Œa€˜–=b€…˜ïâ-tPà ŽYçïÉj€Éj€ô$=b=bÉj€g€I>Us0Ô0Ôg€Œa€ÕŸ€Œa€˜–€Us0Ô 5ú—€ 5s€jUs€,€€,€€,€€,€s÷€s÷€€,€˜–€Œa€¤Ë€g€g€Us$Ÿ 5 5[€0Ô= [€UsUsg€[€[€= 0Ô$ŸUs$Ÿj+Ä|7777–BUFRbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÂLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@H0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡+c\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð„!B„!B„!B„!B€BB„!B„ !BB„ðB„!B„!ctÿtüs÷€g€Œa€Œa€¤Ë€¤Ë€±€Ûºçï$ø±€±€g€gƒ“†þŸcbZŸcbZbZèHbZbZs÷€çï$øÃô$Ï…±€±€¤Ë€Œa€€,€˜–€Œa€¤Ë€s÷€˜–€½5€±€¤Ë€Œa‚ŸcŸctÿtüs÷€€,ƒ“†ÿtþŸcŸcbZèHn6ô$n6ô$ô$èHtüŒa€ÃP˜–€s÷€g€€,€Œa€¤Ë€¤Ë€±€¤Ë€Œa€Œa€Œa€s÷ƒtÿtüô$zô$ô$Œa€½5€±€Œa€˜–€gƒtþbZŸc“†ü˜–€˜–€˜–€Œa€¤Ë€g‚ŸcbZbZô$zn6n6bZs÷€Œa€˜–€¤Ë€Œa€˜–€€,€€,€s÷€Œa€¤Ë€½5€½5€±€¤Ë€s÷€g€7777>BUFRbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÂLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô@\0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð!B„!B„!B„!B„!B„!!@ð!B„!B„!B!B„!B!„!`Œaƒ“†ÿtþŸctÿtüÃPO±$øÏ…±€½5€±€±€ÃPçïÏ…Ûºô$C|YO±1-YÛº½5€½5€±Ã1-ÃPçïÛº½5€±€¤Ë€˜–€˜–€¤Ë€¤Ë€g€€,€€,€Œa€¤ËY¤Ë€¤Ë€˜–ƒ“†ÿ“†þbZn6èH˜–€g€g€s÷ƒ“†ýn6èHn6zzô$èH“†þbZbZbZn6týèHn6zzèHg€±€±€ÛºÛº¤Ë€Œa€˜–€Œa€Œa€±€ÃPçïÛºÃPÃP½5€½5€½5€½5€±€˜–€ô$bZ¤Ë€Ï…Ï…½5€¤Ë€˜–€€,€s÷€˜–€g€€,€¤Ë€Ï…±ƒ“†ü¤Ë€ÃP±ƒtÿtüg€g€€,€½5€ô$$ø7777>BUFR&bÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔBUUUUUUUUUUUUUUUUUUUUU^sœç9Îsœç9Îw½ï{Þ÷½ï{Þ÷½ï{Þ€!B„!B„!BˆB„!B„!B„! cÆ1ŒcÆ0Št%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUPUUUUUUUUUTQQ@UUUEP@TUð `½5€[€= j 5j0Ô$ŸŒa€Œa€˜–€€,€g€s÷€s÷€s÷€= +Ä}€…€…€Œa‚±²|$ŸI>s÷€˜–€s÷€Usj 5 5[€s÷€Œa€g€I>I>s÷€[€g€I>s÷€€,€Œa€˜–€¤Ë€¤Ë€ÕŸ€Œa€g€I>Us$Ÿ$Ÿ0Ôg€UsI>$ŸUs˜–€= 7 ú—€Œa€I>= 0Ô$Ÿ+Ä|= $Ÿ$Ÿ+Ä| 57 ‚±²+Ä}€…€€,€Œa€I>$Ÿ 50Ô€,€Œa€0ÔI>UsI>j$Ÿj+Ä|$Ÿ0Ô$Ÿj±²~±²|7 ú—€…€…€…€…s‚7 €Œa€Œa€O€Œas‚±²|I>j˜–€= ±²| 5j77775BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô€0I$’I$’I$’’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶Ûm¶Ûm¶ÐŠøFS¥mpC!Lt%Kc\øFS¥mpC!Lt)lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUEUPUTEUUUUUUUUU@@ð `= €,[æ1-[æ=bÉj€½5€±€$Ÿ$ŸI>$ŸI>g€±€½5€Œa€I>I>0Ô$Ÿ 5j$ŸUsŒa€g€g€Us 5$Ÿ0Ô+Ä|j$Ÿ0Ô 5= [€g€0Ô7 ss€…€…‚±²|0Ô= g€±€g€= 5±²|= 7 €[€= j[€s÷€s÷€Us= Us$Ÿ±²~±²| 5I>Œa€ô$Y=bô$$ø1- Žçï±€€,€s÷€Uss÷€±€˜–€= 5 5$Ÿ+Ä|0ÔUs$ŸŒa€¤Ë€Us[€[€g€Us0Ô 5±²}s€O€Oú—€j 57 €Œa€O€Œas€Œasss€…€…€…‚±²}€…s€7777…BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô€(0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’Km¶ÐŠˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)ŽÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUEUUUUUUQUAUUUUUUUUUUUð as€Œa€O€O€Œas€…ú—s€Œass€…sú—ú—‚±²|+Ä~±²~±²~±²~±²}€…€…€O€Osú—€$Ÿ˜–€= 5 5 5j 5+Ä| 5 5$Ÿ= [€g€0Ô0Ô0Ôs€Œa€O€Œasƒ+Ä| 5 5 5 50Ô0Ô$Ÿ= $Ÿ 5 5j+Ä| 5$Ÿ 5jj$Ÿ±²~±²|j0ÔÕŸ€çïŒa€˜–€ÕŸ ŽÕŸ€±€Œa€g€g€0Ô= 0Ô 5 50Ô= [€s÷€s÷€Us 50Ô0Ôg€±€±€ô$çïÉj€Éj€±€¤Ë€Œa€€,€I>$ŸUsŒa€ÕŸ Ž7777…BUFRæbÿ« fÔ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô€<0I$’I$’I$”’I$’I$’I&Ûm¶Ûm¶Ûm¹$’I$’I$’[m¶Ûm¶ÐŠ„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©lkŸÊt­®ˆd)Ž„©sáN•µÀ …1Е-sàÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUU@UUUUTUTQUUUUUUUUUUUUUUUð aÃÉj€s÷€¤Ë€s÷€0Ôg€±€ÕŸ€½5€€,€[€jú—‚7 €…ƒ+Ä+Ä+Ä| 50Ô0Ô= I>Us= jj 5$Ÿ 50Ô˜–€±€¤Ë€½5€Œa€[€jú—‚±²}ú—€Œa€Œa€Œa€Œaú—ú—€…€…ú—€…‚±²}ú—ú—€$Ÿ$Ÿ$ŸI>UsUs0Ô+Ä|$Ÿ+Ä|$Ÿs÷€Œa€±€ÕŸ€½5€g€[€[€Uss÷€˜–€Œa€Ûº¥$[æ$øÃ Žô$Ûº˜–€¤Ë€Œa€[€[€¤Ë€½5€ÕŸÃ Žô$Éj€ÛºÃ1-ô$ Žô$ô$Éj€½5€Éj€ÛºÕŸ€˜–€[€s÷€Œa€s÷€Œa€˜–€Œa€Éj€ÛºÉj€ÕŸ€¤Ë€Éj€ÕŸ€ô$7777…BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô€P0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶Ûm¶Ûm¶à‹N•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðU@UUUUUUUUUUUUUUUUUUUUQUEPQUUð `ÛºÕŸ€s÷€0Ô 5+Ä~7 ‚7 s€Œa€…‚±²|= s÷€Œa€¤Ë€Us= = I>Uss÷€¤Ë€˜–€Œa€g€UsI>0Ôj$Ÿ0Ô= s÷€Œa€˜–€ÛºY$øŒa€s÷€g€Œa€Œa€±€¤Ë€¤Ë€˜–€Œa€s÷€s÷€[€I>[€Us[€I>€,€UsŒa€0Ô0Ô$Ÿ= = ŒaY$øô$ ŽŒºtP€¤Ë€¤Ë€¤Ë€g€€,€g€€,€€,€g€€,€ 50Ôs÷€0ÔI>[€g€Us 5+Ä|˜–€j[€I>j±²|$Ÿ$Ÿ±²~±²~±²| 5= $Ÿ$Ÿ 5+Ä| 5±²~±²| 5= I>[€[€[€s÷€±€Ûº¤Ë€7777…BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô€h0I$’I$’I$¤’I$’I$’I6Ûm¶Ûm¶ÛmÉ$’I$’I$’[m¶ÐŠ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1Е-sáN•µÀ …1ÐÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUAUUUU@UUUUUUUUUPTð `Éj€g€½5€ÕŸ€çïI—hÃÕŸ€½5€ÕŸ€Éj€±€±€¤Ë1-ÃçïÛºÉj€ÛºÛºÕŸ€Ûº½5€˜–€ô$±€g€Œa€s÷€[€[€[€g€0Ô0Ô0Ô[€g€[€ 5+Ä~±²~±²+Ä|+Ä+Ä| 5I>s÷€[€s÷€g€s÷€g€$Ÿ0ÔI>˜–€s÷€s÷€I> 5 5+Ä~7 ‚7 ‚±²~±²~7 ‚7 ƒ+Ä|I>€,€s÷€Œa€[€= Usg€s÷€Œa€Éj€½5€±€¤Ë€½5€Éj€€,€€,€[€s÷€[€Usg€g€Uss÷€g€UsUs[€€,€€,€˜–€¤Ë€±€½5€Éj€Éj€I>€,€[ƒ+Ä+Ä| 57 ƒ+Ä|ú—€7777…BUFR&bÿ« fÔ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô‚UUUUUUUUUUUUUUUUUUUUUUUUUUUU_{Þ÷½ï{Þ÷¼„!B„!B„!„!B„!B„!BÆ1ŒcÆ1ŒcÆ1ŒcB„!B„!@Š•-sáN•µÀ …1Е-sáN•µÀ …1Ж5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„dÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUð `Œa‚7 ú—€ 5I>¤Ë€Usjô$Y ŽYÛºÕŸ€ÉjYYçïÛºÕŸ€Éj€ÛºçïÛºÕŸ€±€˜–€±€±€±€ÕŸYÛº±€= j0Ô$Ÿ$Ÿ7 ‚±²~±²~7 € 5[€€,€Œa€s÷€˜–€Œa€Œa€s÷€s÷€g€g€€,€s÷€€,€s÷€€,€Œa€˜–€±€½5€˜–€¤Ë€½5YÛºÕŸ€Éj€ÕŸ€ÛºYYô$ ŽY ŽÛºô$ÛºÕŸ€½5€g€g€[€[€[€g€€,€¤Ë€Ûº˜–€[€0Ô0Ô$ŸI>±Ã$øYô$$øYg€s÷€g€Us0Ô 5j= ±=b€…h ޽5€Œa€s÷€s÷€çïô$ Ž$ø77775BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÀ0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶Ûm¶Ûm»`‹:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×DÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUEUUUUUUUUUUAUUUUUUUUUUUUUUUUUUð a$ø ŽÃY±€g€= j±²|= I>UsUsUsg€s÷€s÷€˜–€˜–€ÕŸÃçïô$ô$ô$ÛºÉj€˜–€s÷€Œa€˜–€I>I>g€Œa€Œa€g€g€Us= Us= I>UsUsI>I>[€[€I>I>+Ä+Ä| 5$Ÿ$ŸUs±Y$øÃô$ÛºYçï$ø$øI—I—YYÕŸ Žô$Œa€s÷€0Ô0Ô 50Ô€,€çï=b=bI—I—ÕŸ€½5€½5€ô$ ŽÃÃ$øÕŸ€Œa€Éj€ô$Ûº˜–€Éj€Éj€[€0Ô[€½5€çïô$±€±€¤Ë€¤Ë€Œa€±Yô$YÛºÃÛº½5€¤Ë€g€˜–€€,€s÷€7777€BUFR¶bÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!bLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÀ,0’I$’I$’I)$’I$’I$’M¶Ûm¶Ûm¶ÛrI$’I$’I$–Ûm¶ÐŠ2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBT¶5Ï„e:V×D2ÇBTÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ð@ð \Ï…$ø&\\À7±Ðu~ º(AYÏÞ“à ëE+|Ð] ÌwÁ[æ‚“.&\ 'ÀŒ0 'À0ÔUÌc Yø$ŸReÀ†Gçïb$ø>¸Ø ®`O€-ÆÀŒa€a¨Ŭ Èw@/M`@@= I>† ?xýà6î€X€@ÉjzkbZÜlÈw@I>’|$ønè 'ÀŒ0$ŸZàº(A1-’ÕV~ 'À~ð$ŸReÀzŒa€Ï…ô$IðW02Z mÝYIðõˆ @ܸ1—PLK@dµ@s÷YU̬üB@ = dµ@½5·t²&\ L¸³ð= jÏÀÕŸzk%ªé¬ ÓX™p#`3á@Ûº«?V~ÝÐB@*¹€f;à¤Ë€Éj€7777€±BUFRæbÿ« fÔ  2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÀ@0’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶Ðж5Ï„e:V×D2ÇBVƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ¦Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUU@UUUUUUUUUUUUUUUUUUUUUýà`½5€¤Ë€˜–€€,€Éj Ž$ø$ø½5€s÷€g€[€OX€= $Ÿ$Ÿ 50Ôj0Ôg€s÷€[€g€[€€,€€,€s÷€OX€0Ô0Ô 5¥}~+k‚¥}|ú>€€,€ú>€€,€ú>€ 5= ± Žô$ô$ô$1-$ø$ø ŽÉj€½5YY[€[€g€Éj€s÷€j$Ÿ= OX€Œa€çïY$ø1-1-$øÃYçï[怅[æI—1- ŽÏ…O±€ô$Ï…Ã$ø$ø1-I—=bO±=b=bÃçïÃ$ø=b$øÃ ŽÃYÏ…½5€½5€¤Ë€˜–€Œa€Œa€Œa€˜–€Éj€çïÛºÉj€±€Œa€Œa€Éj€½5€½5€˜–€½5€Éj€±€Ûº7777€BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÀT0$’I$’I$’II$’I$’I$’m¶Ûm¶Ûm¶Û’I$’I$’I$¶Ûm¶Ûm¶ÛmÛ`‹JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUTUUUUUUUUUUUUUUUUUUUUUUUð `ÕŸ€˜–€= j€,€€,€Œa€I>7 ƒ+Ä|I>s÷€Œa€Us0ÔUsUsUss÷€±€˜–€€,€¤Ë€g€s÷€Us7 ú—ú—€…s‚7 €$Ÿ±Ã=bYYYÛºô$çï ŽÃUÌUÌh[ætPh1-çïÕŸ€½5€¤Ë€˜–€˜–€Éj€çïÃ=b=b ŽYô$ô$Y ŽÛºçïYçïYçïÉj€Éj€¤Ë€±€˜–€¤Ë€˜–€½5€Ûºô$Ãô$ÛºÉj€Ûºô$ÃI—$øYô$ÕŸ€ô$ô$½5€±€˜–€g€Œa€Œa€g€g€¤Ë€Éj€Éj€Éj€Éj€ÕŸ€Éj€ÛºÃ Žô$½5€¤Ë€ÕŸ€Éj€¤Ë€¤Ë€˜–€˜–€Éj€˜–€7777€BUFR&bÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!ÒLEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔÂUUUUUUUUU]kZÖµ­kZÖµ­kZÞ÷½ï{Þ÷½ï{Þ÷½ï{ç9Îsœç9Îsœç9Îsï{Þ÷½ï{Þ÷½ï{Þô!B„!BŠB˜èJ–ƹðŒ§JÚà†B˜èJ–ƹðŒ§JÚà†B˜èJ–×>”é[\ÈS SçÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUEUUUUUUUUUUUUUUUUUUUUUUUUð `±YÃ1-1-ô$YYÃÃYYY Žô$Éj€¤Ë€±€¤Ë€s÷€¤Ë€+Ä| 5 5+Ä|$Ÿ= [€g€= = UsI>= I>[€I>UsI>0Ô0Ôjj0Ôg€ۺÃ=bI—=bÃÛºçïçïÕŸ€çïô$ ŽUÌÃô$çïÉj€¤Ë€˜–€Œa€€,€€,€€,€˜–€±€ÉjYçïÛºÛºÛºÛºô$YY Ž$ø$ø$øô$çïçïô$çïô$Y1-€…I—ô$ÕŸ€ÕŸ€ÕŸ€ÉjY$øUÌ Ž ŽÃ Ž1-$ø1-ô$ÛºÕŸ€½5€Éj€çï$øtP½ŽtP1-ô$çï77775BUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k„C!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUTUUUUUUUUUU `çïô$Yô$ÃY=bC|C|1-$ø$øçïçïçïÃ1-[æ[æ$øYY ŽYô$C|O±C|$ø$ø1-ÃÃYçïçïçïô$ÃPÃPÏ…YÛº Žô$Ï…Ï…Ûº ŽÃô$çïçïÛºçï¤Ë€Œa€[€ 50Ô$Ÿ 5$Ÿj[€OX€Œa€g€€,€g€s÷€½5€çïC|1-$øçï Ž ŽÛºÛº¤Ë‚™H}hâ-‚™H|OX€çïÃP½5€˜–€Œa€[€g€C#€˜–€ô$$øô$YÃP½5€¤Ë€½5€Œa€±€¤Ë€g€€,€¤Ë€ÃPY=b€…€…h¥$˜ï±Y=b1-=b ŽÃPÏ…ÃPÃP7777ŽBUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô0I$’I$’I$’’I$’I$’I$Ûm¶Ûm¶Ûm·$’I$’I$’Im¶Ûm¶Ûm¶Û¶Û`‹pC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!Lt%Kc\øFS¥mpC!LÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU `¤Ë€˜–€s÷€Œa€˜–€¤Ë€±€½5€ÛºçïÛºÃP±€¤Ë€½5€Ï…1-1-ÃYYçïô$çïÏ…˜–€˜–€s÷‚™H~6€OX€±€½5€Ï…€,€ÃPYÏ…çïçï ŽYçïۺυυçïô$çïô$YÃÃô$Ï…ÃPÃPÃP¤Ë€±€ÃPۺυ Ž1-=bC|Y ŽÛºÛºÏ…ۺυÃP±€˜–€Œa€¤Ë€ÃPà Žô$ô$˜–€½5€½5€±1-tP‚Ið¥$€Ï…Ï…çïçïçïÃPOX€C#€g€¤Ë€¤Ë€g€OX€= = C#€C#€C#€OX€g€g€s÷€= $Ÿj$Ÿ[€½5Y ŽÃÃ1-7777ŽBUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô40’I$’II$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÛvÛ`Št%Kc\øFS¢–ƹðŒ§JÚà†B˜èJšçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUPUUUUUUUUUUTýàaO±[æ1-$ø$øÏ…Ï…çïYô$Yô$çïÉj€½5€Éj€¤Ë€˜–€Ï…Y ŽYÛºÉj€±€Éj€½5€¤Ë€€,€€,€g€[€= €,€Œa€½5€Ûºô$YÃO±[æ[ætPtPhO±$øÛº½5€€,€g€[€[€[€s÷€Œa€Éj€[€€,€½5€Œa€[€= = [€s÷€˜–€OX€0Ô~¥}| 5I>¥}~¥}|Œa€±€OX€ô$[æI—1- ŽÉj€¤Ë€[€g€±€Œa€OX€OX€$ŸOX€= I>s÷€Ï…$Ÿ 5g€Œa€çï±€½5€çï±€¤Ë€Ï… Ž$øI—tP=bÏ…˜–€g€I>$Ÿ}tP€ú>tPtP€7777ŽBUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<ÔL0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶ÐŠc¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[Ù£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUUUUUUUUUUUUUUUUUUUUUQUUPUUð c+Ä|0Ôg€¤Ë€[€I>I>s÷€˜–€Ûº=b=b=btP€…½Ž‚Ið çÉÃtP=b=bI—1-[æ˜ï¥$˜ïUÌ1-=b$ø$øUÌ[æÃ1-çï ŽÛºçïÕŸ€±€€,€¤Ë€±€½5€çï Ž1-€…h1-=b Ž Ž Ž=bUÌI—¥$€…1-Y1-YÛºçï±€€,€$Ÿj[€Œa€½5€Us[€€,€¤Ë€I>[€˜–€±€¤Ë€g€Us$Ÿj 5$Ÿ+Ä|ú—€Œa€Œasú—€jj$Ÿ0Ô= 0ÔUsI>g€= j 5±²~±²~±²~±²|Œa€Œa€Œassƒ+Ä|= 0Ô±€Œa€Us= Us½5€7777ŽBUFRæbÿ« fÔ 2€ÀÔÕÖרÙÁ Á Á +,-ZZ!’LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ô`0 $’I$’I$’RI$’I$’I$›m¶Ûm¶Ûm¶ä’I$’I$’I-¶Ûm¶Ûm¶ÐŠçÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡*[çÂ2+k€" c¡Kc\øFS¥lÙ£díâ$TÿøñÄÀÄÀÈ´ÐдÀ€ðUT@U@U@UUUUUUUUUUPUUUPUUUUð `Éj€¤Ë€jjj 5±²~±²~±²|±²|j+Ä}ú—‚7 €$Ÿ€,€½5€$Ÿ[‚7 ‚±²+Ä~±²~7 ‚±²| 5[€s÷€$Ÿ0Ô$Ÿ±²}ú—‚7 ƒ+Ä~±²~7 €= ±€Œa€Éj€ÕŸ€€,€€,€[€s÷€s÷€Œa€ô$ô$=b$ø=bÃ1- Žô$ô$Éj€Éj€ÕŸYY$øô$çïçïYYçïô$ô$YÉj€½5€¤Ë€€,€[€gƒ+Ä~±²}€…€…‚7 ‚7 ƒ+Ä|jjjj$Ÿ= $Ÿ$Ÿ0ÔI>I>Us[€I>$Ÿ0Ô$Ÿ€…€…‚±²}ú—ú—ƒ+Ä|= çï1-à ŽçïÛºÉj€ç€±€Éj€UsÉj€Ûº˜–€7777ŽBUFRbÿ« fÔ 21ÀÔÕÖרÙÁ Á Á +,-ZZ!<LEICESTER CENTRE 1% €€€t#S“tÐŒ @@<Ôt!UUUUUVªªªªª¨"ÜÈS RØ×>”é[\ÈS RØ×>”é[\³FÈ!ÛÄH¨ÿðâ ‰‰‘i¡¡ià8€ªªªª*ªªªŒøP0@@ýKÁÐ@F0ÀÀBÀF0ÁXÙ>O€„€ 5$ŸÐ@ýKÁXÙ>€„€*¹€^šÀs÷€dµ@X€@jÏÀjÏÀ 5j*¹€F0À 'ÀF0ÀýKÁ•â>$Ÿ„€„€j 5€ 5F0ÀF0Às÷€s÷€s÷€€,€z*¹€ 57777dballe-7.7/extra/bufr/synotemp.bufr0000644000175000017500000000073212652630043014355 00000000000000BUFR2be €É–A A!øÿÿÿûëáw­ˆðŒ÷äÿþÿÿÿü6|è ê«;@ N €%ZÕk^É>ê–¥ൠ¢sFLb”<Ü  ÆŒƒÅðœáÿÿÿÿð Íˆ€Q/æ¢7ˆÿáåöAâ¼>‚qÌ>¾˜ÑUMÎ ˆ?ÿì÷çßHº*=ö|½g»àxÍ_·†ê¿ÿÿØÿÿÿÿü  ú 'äÅ+­”_ÿÿÿÿò0°ÿÿ®ÂŒÀrÿÿÿÿÌ€d ¸/ÿÿÿÿøÜ²ÿÿÿÿÿ 4 ¿ÿÿÿÿåPPTÿÿÿÿüZ€ÃÿÿÿÿÿhàŸÿø­uŸÿÿ‚ð ÿÿÿÿþ<ÀRAÿÿÿÿÆ@´ OÿüYºÿÿÿÁ,@\‹‹·g‚€%¿ÿÿÿÿä`Fpÿÿÿÿüª À„„ÿÿÆ;¹ÿÿü0_ÿÿÿÿòX#àÿÿïÿÿð;ÁÿÿÿÿÉ`ð/ÿÿÿÿù€á ÿÿŽ—‹ÿÿøà¿ÿÿÿÿåPx8'ÿþ?Þ_ÿÿàd 3lÇûËŒ‚€ p_ÿÿÿÿñ¸P| ÿÿÿÿþZ .ÿãõåÿþ˜oÿüƒ¼ùT-| x0`páÄÎ8Là‡ œ8pá3„Î8á‡8p™Ã„À8Lá3‡ œ&áÂd€@UcF4hÑ£F4hÑ£F\hÑ£K4jQ¥F5(Ò£F”iQ£FJ4¨Ñ£F¥4hÑ£R4hÑ©F4hÔ£F4iñ£F”hÑ£FJ4hÑ£F¥4hÑ£K4¸Ñ£K4¸Ñ£K4¸Ñ£K4¸Ñ£K4¸Ñ£R4hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hѥƔhÑ£F.4hÓãF4¸Ñ£K4¸Ñ£K4¸Ñ£K4¸Ñ£K4¸Ñ£K5(Ñ£F\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hѥƔhÑ£F.4hÒãF.4hÓãF0‡ÿÿïß¿~ýû÷ïß¿þýûÿÿÿÿÿÿÿÿÿßÿÿÿÿÿÿÿÿÿÿÿ÷ÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿ÷ÿÿÿøP¢ÿ`IÀö ×€¸ÈtTHÌ(É ?Ûxò rÄÎ7777dballe-7.7/extra/bufr/vad.bufr0000644000175000017500000001012012652630043013241 00000000000000BUFRŠN€ Ý  ÿÿ)Ö‚  )h,€!"ÁÁ Á Áy}G  ! ! 2*ÿÿ >좰ٛˆùYàoãÿþ ¸‘QÿÁµ‘@L ø7777BUFRšN€ Ý  ÿÿ)Ò®  )h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좰ÚL¨öøwÓÿþ ¸}!ÿÿÿÁµ d?ÿÿø>‚ §ÿÿÿÊ=Âàÿÿÿà7777BUFRšN€ Ý  ÿÿ)Ôß  )h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좲L¨öøwÓÿþ ¸~yÿÿÿÁµ ‰?ÿÿø>‚çÿÿÿÊAA´ÿÿÿà7777BUFRŠN€ Ý  ÿÿ)Ú^  )h,€!"ÁÁ Á Áy}G  ! ! 2*ÿÿ ¾ì¢²™Áˆó¬ÀGÿþ Ä¡éÿÁw0 ø7777BUFRšN€ Ý  ÿÿ)ÖŽ  )h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좳ZL¨öøwÓÿþ ¸€ ÿÿÿÁµ?ÿÿø>‚ÇÿÿÿÊAôÿÿÿà7777BUFRŠN€ Ý  ÿÿ)Ú^  )h,€!"ÁÁ Á Áy}G  ! ! 2*ÿÿ >좳Y›ˆùYàoãÿþ ¸YÿÁµ‘ O ø7777BUFRšN€ Ý  ÿÿ)ØÅ  )h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좴šL¨öøwÓÿþ ¸ƒ±ÿÿÿÁµÐ˜?ÿÿø>‚ÇÿÿÿÊAÂÿÿÿà7777BUFR‚N€ Ý  ÿÿ)Þ:  ")h,€!"ÁÁ Á Áy}G  ! ! 2"ÿÿ ¾ì¢µÁˆó¬ÀGÿþ ¸ yÿÀ7777BUFRšN€ Ý  ÿÿ)Úƒ  )h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좵ÚL¨öøwÓÿþ ¸~©ÿÿÿÁµ ?ÿÿø>‚'ÿÿÿÊ@Âèÿÿÿà7777BUFRŠN€ Ý  ÿÿ)Þ:  ")h,€!"ÁÁ Á Áy}G  ! ! 2*ÿÿ >좵ٛˆùYàoãÿþ ¸† ÿÁµ‘°I ø7777BUFR’N€ Ý  ÿÿ)Üp  )h,€!"ÁÁ Á Áy}G  ! ! 22N Æ>좷L¨öøwÓÿþ ¸}ƒIÿÿÿÁµ‘Px?ÿÿø>‚L‡ÿÿÿ7777BUFRšN€ Ý  ÿÿ)Ûë  )h,€!"ÁÁ Á Áy}G  ! ! 2:×× J¾ì¢·š/c(ý/`SlxórÛ+ŸÿÂMRf»ÿøB FJèÿpÌñ}Oÿà7777BUFRÔN€ Ý  ÿÿ)áb  *)h,€!"ÁÁ Á Áy}G  ! ! 2tU‘¾ì¢·š3…êõ€RÓÿþlwaÿÿÿÁ0s?ÿÿø#ñì‡ÿÿÿâ=‚ÿÿÿà¨Ç°AŸÿÿü¨ùsÿÿÿƒ!ÿÿðg#ô"Oÿÿþ ¬€QÿÿÿÁÎ?ÿÿø<ò'ÿÿÿ7777BUFR‚N€ Ý  ÿÿ)ãM  /)h,€!"ÁÁ Á Áy}G  ! ! 2"ÿÿ ¾ì¢·™Áˆó¬ÀGÿþ ¸›ÁÿÀ7777BUFRšN€ Ý  !ÿÿ)Þd  ")h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좸ZL¨öøwÓÿþ ¸IÿÿÿÁµ‘Py?ÿÿø>‚*ÿÿÿÊD¤ÿÿÿà7777BUFRŠN€ Ý  !ÿÿ)ãM  /)h,€!"ÁÁ Á Áy}G  ! ! 2*ÿÿ >좸Y›ˆùYàoãÿþ ¸€!ÿÁµ‘°N ø7777BUFRšN€ Ý  &ÿÿ)à–  ()h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좹šL¨öøwÓÿþ ¸„ÉÿÿÿÁµ’k?ÿÿø>‚VÿÿÿÊ=‚tÿÿÿà7777BUFRšN€ Ý  +ÿÿ)↠ -)h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좺ÚL¨öøwÓÿþ ¸~ƒ¡ÿÿÿÁµ‘t?ÿÿø>‚ çÿÿÿÊCˆÿÿÿà7777BUFR’N€ Ý  +ÿÿ)æ   6)h,€!"ÁÁ Á Áy}G  ! ! 22ÿÿ >좺ٛˆùYàoãÿþ ¸‚yÿÁµ’I ø>‚\ Dÿ7777BUFRšN€ Ý  0ÿÿ)ä?  1)h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좼L¨öøwÓÿþ ¸}„!ÿÿÿÁµpj?ÿÿø>‚ GÿÿÿÊD‚øÿÿÿà7777BUFRšN€ Ý  5ÿÿ)æ,  6)h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좽ZL¨öøwÓÿþ ¸}‰ÿÿÿÁµ r?ÿÿø>‚ gÿÿÿÊ@‚tÿÿÿà7777BUFR’N€ Ý  5ÿÿ)ù¹  )h,€!"ÁÁ Á Áy}G  ! ! 22ÿÿ >좽Y›ˆùYàoãÿþ ¸~IÿÁµ‘°L ø>‚\ ÿ7777BUFRšN€ Ý  :ÿÿ)è&  ;)h,€!"ÁÁ Á Áy}G  ! ! 2:N Æ>좾šL¨öøwÓÿþ ¸‚ÿÿÿÁµàƒ?ÿÿø>‚gÿÿÿÊC|ÿÿÿà7777BUFRúN€ Ý  ÿÿ)ç±  :)h,€!"ÁÁ Á Áy}G  ! ! 2š×× J¾ì¢À/c(ý/`Slx\ lÚüïÿÁ3n@†hqÿø'-æäžÿÿý¾Àøxßÿࢷè#àÿü´ÿ‘ôÿÿ‚¢ŸÀb¾‡ÿðUÓ¼ —Éþ êvñ/ÿÁcOB¿ÿø-%ð #ý?ÿ¼¼“ïÿທ R„ÿü°ú buÿƒÀ¼BÿðaÃüÈ®þ h|‚ÁŸÿÁ’ï`6Áÿø3äC׿ÿ{¿A4oÿàÒw¨ ®Àÿü¬ÿÝÿƒa À:¼Wÿðm´H#ÿþ å†ÉÿÁ±€.Eÿø9 Câÿÿ:Ä@ô~÷ÿàêXH!>ÿü©r ŸÿƒÁ à¸@[ÿðy¤ ÈLþc„ƒ¯ÿÁòppi ÿø? £æÿùÁAp}ÿá(0#Òÿü ¥ Áòÿ„ ¡`t>[ÿð…”(ÊÿþáƒèüŸÿÂ"0AÿøE,£úÿÐA€ü~Çÿáøyÿü$;åêŸÿ€7777BUFRÞN€ Ý  ÿÿ)üº  )h,€!"ÁÁ Á Áy}G  ! ! 2~U‘¾ì¢À3…êõ€RÓÿþ4€éÿÿÿÁЄ?ÿÿø'øgÿÿÿF>Â0ÿÿÿàµGàIÿÿü8þ Cÿÿÿƒ9á2ÿÿðmcü&Oÿÿþt€„¹ÿÿÿÁç“?ÿÿø@Gÿÿÿf@ÂDÿÿÿà7777dballe-7.7/extra/bufr/C05060.bufr0000644000175000017500000000345412652630043013260 00000000000000BUFR,Pÿ Ù €É4QRC_`a=…<ñ  ÿÿÿÿÿÿÿÿ¨ ‡“ìàwÆ:úb\À¾äúüq ‘¨WÿÿÀPG¼úÑ*ˆ•Dk{c ©Q*‚è•C{zóiÌP  ‘*‚è•CÛ|»e„´Ð ˆQ*‚h•CÛ|£eÄ>Z‘Ñ*{(•N#pËZè ÐJ ²‘*€È•R»m›YCü d~ôÑ*‚è•ZógÃH¼4 Pfqú‘*„•[ƒg›G<0 glý*„¨•\#g{G , Ðu ‘*‡H•asc MSäÐx(Q*‰(•c b RóäPƒÏF*È•gËakDt Ћž]*¨•j+_“9d ‹ š_*È•j³_k8l P–^‚{Ñ*‘h•m[`› ÈP¹ Ù‘*šè•u3Y‹L P×ÿ+Ñ*©(•Vbõ#ÄÐôrƒvQ*³è•‹PºëÔ   ý¶Q*º(•”ûMòЃü Ñ  ¬ã‘*½¨•š[JÂ< ) x„Ñ*½H•žkHzÄ”x Q; '/‘*³(•¦G’ç¨Q= „4Ñ*¯h•¦ÛGBò¨ÑL Ü[Ñ*¤ˆ•®“CCä´Qm P°‘*…è•ÁK>ì¤Q€ „â*y•ÏÃ9²é dÑ’ ¸Q*qH•Þ+5ZïÄ`QÆ ñ“Q*U¨•ÿû)"Õ|”QÊ ã…œQ*Pˆ–û(RÛ”ê mî*E–£âåL<’ Ɔf*4è–6‹’öl’ ÄgÑ*4¨–7kbölÒ* š‡*.h–@û2å|d’5 v†¡‘*(È–Hã òýìtÒX çÑ*¨–c»’úœŒ’` ùQ* H–isšú<Œ¬‡?Ñ)üÈ–}bÿÒðP’«G‡“)ô–˜BøZà P¾¸‘)ëÈ–¤âôÊÛDxRËøÖ‘)ãH–¬"ñbÛŒ RÛ Ðù‘)Õ(–¶Ríª×œ€Òé¯Ñ)ψ–¿òêªÎl c[‘)¾h–ÙÂâªÍ|PÓVÊëÑ)ˆ—JÑêÁÔ|Óg©‰ ‘)—"Îjº”Œ“¢4 ‚Q)iè—UzÁ²¦œp!S´ ¥)ZÈ—fr½š£t€ SÌ Ü à)>ˆ—}²¶ò¡¼ &ÓÑЉìQ)5È—‚rµ’ Ä¤(Óç­ Ñ) È—™³2˜ŒÈ'Ôq WÑ(戗´z±rŽäd*”nŠZ‘(æÈ—µz±"Ž\d+TF â ‘(“ˆ˜'Ò Š…ä€KÔf µ >(I˜p žŠƒÜ|TTl¬‹I‘(;(˜~bº‚¼€RT‡ ƒQ( 蘵’œŠzld>ÔœX‹»( H˜ÚªuÌ@”¯7‹ê‘(h˜ÿÒ¥ruLD=T½ŒQ( È™š¢êjÄd3”ÞðŒVQ'ú¨™@Úžc<0'”å è c‘'ýH™HÊžBc$)Tìߌq(è™Qâ rd,-•¨ Ë‘(¨™œ¢b]L<-•~< ‘(@(š(ÚžâP„7U“& ·‘(UˆšLB¡ZQü<•¬ ç‘(t(šyÊ¢òP4@ÕÌîŽ(‘({ˆš²’§BP,L4Ì î)‘({ˆš²’§ZP4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777dballe-7.7/extra/bufr/obs2-101.16.bufr0000644000175000017500000000270012652630043014065 00000000000000BUFRÀb€e  4e}Ky€CL„cH08221 Ày¨Îy¦F€É–A A!Rnž£ê[ÌŽA †™ þÿÿÿýVqïÿÿÿÿÿÉIû_U|(I«¢«-)`@'…nUÿÿãF.®Š˜ÿÿü;ÁΕµXßÿÿ„Ñ>·ªýþ6ÿÿÿÿÿÄÀz€€ƒ*تoÿÿ¾¼ ÿÿÿÿÿ6‡ÐÿÿÿÿæÀdæð/ÿÿÿÿüÄ›X@ ¨`‘cc€¿ÿÿÿÿñÐŒgH0;–é:DLÐR½#ÿÿý`€üjsœŸÿÿ°è ÉLó+ÿÿöÿÿÿÿà€d»€oÿÿÿÿü` — ÿÿÿÿÿ‰â«Á‹T2ÿÿÿU(ÿÿÿÿþbʇ cÐ<ÑÿÿýA@_ÿÿÿÿøÀ'€-á=r¿dµÿÿÿÿß@ŒŽÐ/ÿÿÿÿü$¤h™¸Éÿÿú @¿ÿÿÿÿð@<>t–\â­àDzÿÿÿÿÿ¼æ _ÿÿÿÿ÷X¼ ÿÿÿÿþÿ#h‚0äv!ÿÿþj@/ÿÿÿÿûÀ žÿÿÿÿÿ‚w”ñŸ ®°2-Èÿÿÿÿý®…–ÿÿÿÿÿ¼ð©`_ÿÿÿÿ÷0 O­°Sÿÿò}ÿÿÿÿÕ@N"Id=Àº‰L*\†×ÿÿÿù€¿ÿÿÿÿèÀFàÿÿÿÿüðƒè IÂ;â¡Àðs _ÿÿÿÿõ( èPb—¯Ã¤ÿÿÿÿÜÀP2P/ÿÿÿÿü$ðÿÿÿÿÿn່«p‚ì®`FHÿÿÿÿýÖÂÕÿÿÿÿÿ·@W€Ão¸MuØ  P ÿÿÿÿþëA6ÿÿÿÿÞ ´%Ð/ÿÿÿÿü8„8=‚W!ÿÿø…À¿ÿÿÿÿî°Zðÿÿÿÿþ Aô&|A«˜ÂA<_ÿÿÿÿø 7ò ÿÿÿÿÿ"ÀØB•¡Ëÿþ /ÿÿÿÿü$ƒÿÿÿÿÿ“àYà¿ÿÿÿÿð< ñš \NQ‚ÿÿÿÿÿÂ@ð'_ÿÿÿÿøè° ÿÿÿÿþúÀÁÿÿÿÿà€Üx/ÿÿÿÿü°øÿÿÿÿÿ“à>ˆ éPRß² 2Äÿÿÿÿþ:@ôÿÿÿÿÿà _ÿÿÿÿø˜<€ ÿÿÿÿÿàlÿÿÿÿã xB•t ·ïÿÿÁ™ SæöýŽƒÀ8O0`8pà€ƒpáÀgœpà3€8 áÀp3‡páÀ8pà3‡8 áÀ8páÀ8p XÑ£F4hÑ£F4¸Ñ£F4hÔ£J4iq£F.4hÑ¥Æ5(Ò£F\hÑ¥Æ4¸Ñ£K4¸Ñ£R*4hÑ¥Æ|hÑ£F.4hÑ¥Æ4¸Ñ£F—4iq£F—4iq£F.4hÒãF\hÑ©F•4hÒãF.4hÒãF\hÑ©F•4hÒãF.4hÒãF.4hÑ¥Æ\hÑ©F•4hÒãF.4hÒãF.4hѥƔiQ£F.4hÑ¥Æ\hÑ©F•4hÒãF>4hÑ£F—4iq£F—4jQ¥F4¸Ñ£K4øÑ£F\hÑ¥Æ\hÑ¥Æ4¸Ñ£K5(Ò£F\hÑ¥Æ\hÑ£K4¸Ñ£K5(Ò£F\hÑ¥Æ\hÑ¥Æ\hѥƔiQ£F.4hÒãF.4hÒãF.4hÒãF|hÑ£FŒ7777dballe-7.7/extra/bufr/ed4-compr-string.bufr0000644000175000017500000000101412652630043015567 00000000000000BUFR ^ Ù  ÀÇPà <@BÔµˆÉ‹*Ȫjˆ*‰)éÄ()ˆIêHè(*I ªd Š¨Ê‰*ÉÄ 舩Êh¤ Š¨Ê‰*ÉÄ iè¨H©É*ÉÊd Š¨Ê‰*ÉÉ)©¨ªD 興¤Ë*DH#ì€Àí®‚Uùà#( C`P˜&î"àx}ñO†_ÿð'HsÇ騆5Áç þÿàÿÀÿÿ«l–’ÑU@5 ’úAM©@àÿ€+Ã39AÂÿüÿÀÿÿàǽ@0îâ B â€q‚ÕÂ>Ê÷AJ‚ahE('€VJPR€ù†¥0Zɹ\€Oøÿð?à~üÀÿÿÿøÿþÿð>ÿøÿàóþƒåƒåïÿÿÿàð?ÿÀÿð?ÿÿ@ÿð?üÿÿüÿÿÀÿÿÿü @?°á| SÀ*2‡½HÿÀÿÿàøð?üÿð?üÿÿÀÿð?üÿàÿÿþÿøþÿÿàÿÿüÿð?ÿÀÿð?üÀ7777dballe-7.7/extra/bufr/ed4-parseerror1.bufr0000644000175000017500000000163712652630043015423 00000000000000BUFRŸêÿ Ù !€ÁZÂÂ#Â$Â/Â0Â%Â+Â,AÂ-Â.\PL¤ ©¥§  §-"£ ª/³ŒÝ ‘§`4ÿÿÿÿÿÿÿÿÿøCsK\{ßÿÿÿÿÿ€ÿÿüÿÿÿøÿò?äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿß÷ÿÿÿþýÿÿÿÿÿÿÿÿÿÀ2?ÿÿÿÿÿÿÿÿÿÀú Oìn/ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¨,БUQÐSˆÙÀÆè¡GÈ€?§užeñÿÿÿÿü!Ã¥´õ·ÿøú?ÿÀÿÿÿÿÿüùòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿú¥ÿÿ~ÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿà}'öÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔˆH©Å¨êªI)éÄ )Ê…Ä)*J ìàctP€£ô¨b‚1S¶Ï<øÇÿÿÿÿþã:Øê«ÿü}ÿàÿÿ€ÿÿÿþ?üù?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇýR¿ÿÿ¿Gÿÿÿÿÿÿÿÿÿð ÿÿÿÿÿÿÿÿÿð>ˆû+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿê ä$TU"4„Ud4•E’öp1€¹HQðR© –§¦}ÿÿÿÿÿÈoùm{ÿÿÿÿÿðÿÿÿÿÿÿþGüŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûþÿÿÿÿߣÿÿÿÿÿÿÿÿÿøGÿÿÿÿÿÿÿÿÿøD ýŒ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõ:*Jb ¡û8À[5œ(ÿ›€€Äòɾ‰ÿÿÿÿÿ€d8û¶qªÿÿ.çÿø?ÿàÿÿÿÿ€ÿ#þOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñÿT¯ÿÿïÑÿÿÿÿÿÿÿÿÿü#ÿÿÿÿÿÿÿÿÿü¢þà ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø7777dballe-7.7/extra/bufr/tempforecast.bufr0000644000175000017500000000336212652630043015175 00000000000000BUFRòÈÿ  f€ÂÀÁÃÂÀÁ ÀÁ Á  ÀÁà      Á       Á       Á       Á       Á       Á       Á       Á       Á       Á      Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       Á       ÀÁÃÂÀntemp P@ @øÎ€Bºˆ€¼i@¥`_ËSã0P€ ;¹"$a‚((ªÀê0þçÐ P•gDc¤ @ 8r'm0ÿn¨€0aH\ôQ»dá…áÐZ1>íHЬo›M(ƹ @mA õ4# .ø€%PaòÆu0¬€r¼²¤aˆÓ·WCÿqØñˆÐ'´T½cüÆÚÄ¡‹ºÙÃñÿ‘¦óHP1pI`ÈÆKù @Ûp8` PX€=€cÅñÀpÓ€-à?iP ?R3¦€}hìÀæE@H€ÕQÎÒ!¤pG>•_@hP”P aøÕí "@FZ ,Q„ Y4€ i…À¤æ O€=iÐbD¡¦xlÁ>µµB P› 2dè× &@NoÐ#Q \´H€@iÉÀˆæ@B€ tQ¢„!§E™@ÒÓHè +쑬pI’BÑ7777dballe-7.7/extra/bufr/test-temp1.bufr0000644000175000017500000000252612652630043014505 00000000000000BUFRVb€e  4e}Ky€IpÈo2Ì06181 Vyžyœ, (€ÉD = >–A A!Ü Z££ê[̼Ë0’á¸þÿÿÿý.y(Àzê¬6¸ N €?\há){‚«2¤?ÿÿ,/ÿÿÿÿû¬¤"@Šªš‰x4JÁÂÕPÿÿ†Ø ’éÛÿÿðÌ_Óÿÿþ €mªŸŸÿÿ¤ ýU“ÝÿÿøMÆêÂrž  @=}YMÇÿÿݦ “ªéúÿÿûk¡u70@xlèÿÿÿÿþ žÿÿÿÿÿÁi€`ºQŸÿÿ®ô#3IsWÿÿõŒÿÿÿÿÜÀܪ @£= ʯÿÿÔúÿÿÿÿÿxÒqÞ»0q0FMÿÿÿÿþ0É’ ¿NŒ±ÿÿý,_ÿÿÿÿù##<3Ÿ4²ïÿÿô3È&6Oÿþ~/ÿÿÿÿüœ @•ù-“‚ѽ¿ÿÿÿÿôPZ6° ‚‚Dã·ÿÿæ6ŒFìYÿÿü»„I8¿‰ºPKˆ€R1ðwO ‚] vá– ÿþ>‚s¾Õ(4‡Æÿÿÿÿÿ¥öAÖpúÿÿH Âüß*Šî @ë×ÑB€] ƒR(%{ÿÿŠðm-o/ÿÿñ'¥ ­Ýÿÿþ$/ÿÿÿÿüì„L<9WWÿÿø}‡Ï0jìtðn(ÿÿÿÿþbŸ‚ÿÿÿÿÿÒ‚ø1°_ÿÿÿÿú Z” ÿÿÿÿÿJ ¯¯ßÝËéA@iB8óù¹­((€H­€w5ÿÿøJà¿ÿÿÿÿôð‚Ñ9Éý\Þ¨ÀÀ„*%?;”ÿÿü_ÿÿÿÿúÈK| ÿÿÿÿÿT €Kˆ_ÍÈiá|BàSý¹OÿÿÁ ÿÿÿÿÿ¥°`¿ÿÿÿÿõà `ÿÿÿÿþ¨d 1®?{ŽÓ¨ ð_ÿÿÿÿú(xTͼú®/ÿÿð&Â=_ÅÇÿÿþP/ÿÿÿÿý*€hqø|· ÿÿø ˆ_¯žâ4Qh!Ôåùܧÿÿà)‚ÿÿÿÿÿÎÄØ‡~'×qŸÿÿ€Œ+ÿÿÿÿÿJ€æ UÐÿÿþ0€Œÿð"`žÀÁƒ 0` à3€8 Àƒ€À À`8pg8p3‡8 À`œp@€@eãF4hÑ£F4hÑ£F4jQ¥F4¸Ñ£F—4jQ¥F4¸Ñ£F—4hÒãF\hÑ£K4jQ¥F4¸Ñ£F—4hÔ£J4iq£F—4iq£F.4hÑ¥Æ\hÑ£K5(Ò£F\hÑ¥Æ4¸Ñ£K4iq£F.4hÔ£J4iq£F—4hÒãF”iQ£FJ4¨Ñ£F—4hÔ£J4iq£F—4hÓãF4jQ¥F4¸Ñ£F—4hÒãF\hÑ¥Æ5(Ò£F\hÑ¥Æ\hѥƔiQ£F>4hÑ£F—4hÒãFJ4¨Ñ£F—4hÒãF.4hÔ£ 4iq£F.4hÒãF.4hÔ£J4iq£F—4hÒãF\hÑ¥Æ5(Ò£F\hÑ£K4¸Ñ£F—4iq£F4hÀ7777dballe-7.7/extra/bufr/temp-bad4.bufr0000644000175000017500000000130112652630043014245 00000000000000BUFR¼ë Û €É4‘P„ÿÿÿÿÿÿÿÿÿÿÿÿ“í‘àÕ»Ú“ñP*NÿÿÿÿüÿÿÿÿÿÿÀÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€Ìÿÿÿÿÿÿÿÿÿÿÿüˆ`ÿÿ€ÀÿÿÿÿÿÿÿÿÿÿÿÿüœL?ÿ€©ÿÿÿÿÿÿÿÿÿÿÿü8+ÿÿ€•ÿÿÿÿÿÿÿÿúyêToÿÿÿÿ€“ÿÿÿÿÿÿÿÿÿÿÿÿü$<¿ÿ€…ÿÿÿÿÿÿÿÿÿÿÿüt4ÿÿ€uÿÿÿÿÿÿÿÿÿÿÿüL/ÿÿ€iÿÿÿÿÿÿÿÿÿÿÿûè+ÿÿ€`ÿÿÿÿÿÿÿÿÿÿÿü`1?ÿ€^ÿÿÿÿÿÿÿÿú‰Šdÿÿÿÿ€Fÿÿÿÿÿÿÿÿÿÿÿÿü°%ÿ€<ÿÿÿÿÿÿÿÿÿÿÿü8?ÿ€ÿÿÿÿÿÿÿÿÿÿÿÿüÄ ?ÿ€ûÿÿÿÿÿÿÿúŠÊ_ÿÿÿÿ€úÿÿÿÿÿÿÿÿÿÿÿÿû\ÿ€ñÿÿÿÿÿÿÿÿÿÿÿûü¿ÿ€ãÿÿÿÿÿÿÿÿÿÿÿÿü$ÿÿ€Ýÿÿÿÿÿÿÿÿÿÿÿÿû¬ÿÿ€Òÿÿÿÿÿÿÿÿÿÿÿÿû¬ÿ€Îÿÿÿÿÿÿÿÿú–ªjïÿÿÿÿ€Âÿÿÿÿÿÿÿÿú£Êtïÿÿÿÿ€—ÿÿÿÿÿÿÿÿÿÿÿÿø(¿ÿ€‘ÿÿÿÿÿÿÿÿÿÿÿûHÿÿ€ŠÿÿÿÿÿÿÿÿÿÿÿÿûÔ ÿ€‚ÿÿÿÿÿÿÿÿÿÿÿýÿÿ€ÿÿÿÿÿÿÿÿÿÿÿý¿ÿ€yÿÿÿÿÿÿÿÿÿÿÿúÐÿ€vÿÿÿÿÿÿÿú©jn €7777 dballe-7.7/extra/bufr/generic-bug20140403.bufr0000644000175000017500000000030012652630043015473 00000000000000BUFR`Èÿÿè€ÂÀ"generic @O A3ðC¤7777BUFR`Èÿÿè€ÂÀ"generic @O A3˜+:7777dballe-7.7/extra/bufr/pilot-gts3.bufr0000644000175000017500000000147012652630043014504 00000000000000BUFR8b€[  4[}Õm€M•Te4415614 8m±FB€Á  Á Á ÁE   E = >–A A!¤3ûî«l”ÐЛ*¨ß6“¨ÿýÌ/ÿÿ¿ÀòÀ_ÿ÷ÐBhƒÿÿhÿá Œý /ÿûè’ÿÿ„‚ƒ˜¿ÿïPFnPÿþ M¬ ÿÿÄÁiŽÀ_ÿø 2/” ÿÿ e§ÿáÁ@œBÿüL2 Aÿÿ“‡â€¿ÿòÀú.áÿþb(K ÿÿËP£À_ÿù°‘( ÿÿ,sÿã¢N"ÿütA .ÿÿŒ‘ ¿ÿñЂ 0ÿþƒè ÿÿÇBXz€_ÿùF° ÿÿAÂÿßA5 /ÿü8-"ÿÿ‘мÀ¿ÿð@nqÿýþBÁÿÿÄ€R€_ÿú ÿÿ6á.ÿÞ Œ#ð/ÿûü„$ÿÿ‘}¿ÿìЈÿýêÁÂÿÿÄÁh5_ÿúð’ ÿþ¥ ¯ÿÔ x`/ÿú¼‡ÿÿsA¿ÿö€ ÑÿüÈ€àÿÿ@ÈP_ÿò€( ÿþPÀ\ÿÐ@d `/ÿùô€J–ÿÿ@ !0B„!B„!B„!B„!B„!B„!B‚1€tF4hÑ£F\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ4hÑ£7777dballe-7.7/extra/bufr/synop-groundtemp.bufr0000644000175000017500000001110012652630043016020 00000000000000ISID11 EDZW 030900 BUFR&N  €ÇPþ¤2¶3·¶0·2/³¤ß÷B=g|ÈøN 8ƒÙÿÿÿÿøCjÛg=Ïÿñ,ÿÿÿÿÿw²úˆ.8=þGüŸÿÿÿÿÿÿÿÿÿÿÿÿöÀp«þ˜Oþ£ÿÿÿ¿èÿÿÿÿûú@ÿûú@bÿü ý”÷öP+¦%‚çÿýú?ÿÿÿÿÿÿàÿïÑÿÿÿÿÿÿÿÿÿÿýÿÿñ@¢cK›¡ «1›Ëc¡û8@n¢Á#ïÔA @…Dßó=Oÿÿÿÿÿ€d5Öµ·`ÿÿ ÿÿÿÿÿù?ðiÿÿÿƒ@£ðŒ?üù?ÿÿÿÿÿÿÿÿÿÿÿÿíR©×ýƒßü?GÿÿÿÐÿÿÿÿ÷ô€ÿ÷ô€«ßÿøû«ïì‚çL<ŸÿûôþÿÿÿÿÿÿÀ€ÿߣÿÿÿÿÿÿÿÿÿÿûþÿÿâ‚566†ÆW7v–röp4€ÜˆšHN¯)Á ¾§5{_ÿÿÿÿÿÈk™kV¿ÿþÿÿÿÿÿòàê_|Ç@ÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿþÔ&=ÓÿÀôÿÿ÷ýÿÿÿÿÿHÿÿHjŸÿÿ?² >þÆàDtÃp2ÿÿ¿GÿïÿÿÿÿÿüÀ“ÿýú?ÿÿÿÿÿÿÿÿÿÿ¿ïÿþ(7Fehmarn _gH ÈŽ¤Ž&8|õœút—¶?ÿÿÿÿð †Á¶¸ _ÿâXÿÿÿÿÿÿ î7#÷À\a¸?üù?ÿÿÿÿÿÿÿÿÿÿÿÿí?áWýŸü?GÿÿÿÐÿÿÿÿ÷ô€ÿ÷ô€¬ÿøû KïìŒLAßÿûôþÿÿÿÿÿÿÀaÀaÿÿߣÿÿÿÿÿÿÿÿÿÿûþÿÿâ‰4†Ö'W&rÔgV†Ç6'VWGFVÅöp4€Û+lHy¶ÁiÉç:|ÿÿÿÿÿÈlkz³ÿþ%ÿÿÿÿÿòáž?|Æ àÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿþÕ>?Ó ÿÀôÿÿ÷ý#ÿÿÿÿÿHÿÿHkÿÿ?²0þþÈ QtÄ.ÿÿ¿Gÿïÿÿÿÿÿü¬§ÿýú?ÿÿÿÿÿÿÿÿÿÿ¿ïÿþ(¢Schwerin _gH ²ðD$°#ÜE›òuÆ?ÿÿÿÿ𠆼¶°ºÿÿâ¼ÿÿÿÿÿþÀî/£÷À\a|?üù?ÿÿÿÿÿÿÿÿÿÿÿÿíGaWý0_ü?GÿÿÿÐÿÿÿÿ÷ô€ÿ÷ô€¦?ÿøû#ïìn—LFÇÿûôþÿÿÿÿÿÿÿÿÿÿÿÿߣÿÿÿÿÿÿÿÿÿÿûþÿÿâ‹„w&V–g7vÆBöp4€Ûà4IÇsö€ýùÚçs|ÿÿÿÿÿÈkqjÛµÿþ%ÿÿÿÿÿåeQåËÃ*( hùòÿÿÿÿÿÿÿÿÿÿÿÿÚ4ÁOú!?ÿÿ~ÿÿÿÿÿÿÿÿÿÿÿïéÿïé 8ÿð'öF?ßÙN˜Œÿ÷èÿýÿÿÿÿÿÿÿÿÿÿÿÿ¿Gÿÿÿÿÿÿÿÿÿÿ÷ýÿÿÅ­¬Œ­Ä ìàiµ–øŽ×Áèò…Îù7ÿÿÿÿþÚòÚ-wÿü}ÿÿÿÿÿØÂ4~øŽ‚qƒPÿò?äÿÿÿÿÿÿÿÿÿÿÿÿÿµ¸€ŸôÂðýÿÿýÿ@ÿÿÿÿÿßÒ?ÿßÒèÿÿàOì–o¿²X1, ÿïÑÿûÿÿÿÿÿÿ44ÿÿ~ÿÿÿÿÿÿÿÿÿÿïûÿÿŠ8œ™[Y[ˆÙÀÒi Ääõ'!œñÿÿÿÿü!³°jÏÿøú?ÿÿÿÿÿ°:‹èÛð_á•@ÿäÉÿÿÿÿÿÿÿÿÿÿÿÿÿjï?é„ÿàú?ÿÿûþ€ ÿÿÿÿÿ¿¤ÿ¿¤5³ÿÿÀŸÙ?d`ºaà¿ÿߣÿ÷ÿÿÿÿÿþJGÿþýÿÿÿÿÿÿÿÿÿÿß÷ÿÿ‡'2º¹:¸84·³¤ÐsLg¸±Na;CàßÿÿÿÿøC^ YÝ¿ÿòÿÿÿÿÿþïÿï(PÿÿÿþGüŸÿÿÿÿÿÿÿÿÿÿÿÿö¦?ïÿÿïþ Ÿ£ÿÿÿÿÿÿÿÿÿÿÿûú@ÿûú@WÏÿü ý=÷öF“¦€ÿÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿñJ’C ss{³+‘û8@l±Z$-´A`”Þ3œ¾‹ÿÿÿÿÿ€d6£µÚÌÿÿ8Gÿÿÿÿÿöa#eC ˜a|?üù?ÿÿÿÿÿÿÿÿÿÿÿÿíbáWýŸü?GÿÿÿÐÿÿÿÿ÷ô€ÿ÷ô€½_ÿøû*ï쪗LPÿûôþÿÿÿÿÿÿÁ86¿ÿߣÿÿÿÿÿÿÿÿÿÿûþÿÿâ–”ÖvFV'W&röp4€ØÕIjS/)¼ç\|×ÿÿÿÿÿÈkýkt·ÿþ+Ïÿÿÿÿÿòò?|Æ(Âø8nÿ#þOÿÿÿÿÿÿÿÿÿÿÿÿûShUÿL'ÿÑÿÿÿßôÿÿÿÿýý ÿýý ¬‡ÿþþÉ`ûû(íÓÀ±ÿþýÿ¿ÿÿÿÿÿð5p5oÿ÷èÿÿÿÿÿÿÿÿÿÿþÿ¿ÿø¦%1¥¹‘•¹‰•Éœ€€€€€€€€€}œ 6?ª’ƒCà› NºoÙߟÿÿÿÿÿÀ2ÙÚ³mÿ‡Óÿÿÿÿÿ÷ãÜBÀ!†àHþGüŸÿÿÿÿÿÿÿÿÿÿÿÿöpSþ„/þŸ£ÿÿÿÿÿÿÿÿÿÿÿûú@ÿûú@Tÿÿü ý‘€=÷öF›¦ €óÿýú?ÿÿÿÿÿÿâ/!ßÿïÑÿÿÿÿÿÿÿÿÿÿýÿÿñL‚#«+››+c#{“1û8@kÍ+#Ÿ—à‰´Þ¿%ÿÿÿÿÿ€d7 ¶²Öÿÿ]Çÿÿÿÿÿö`í2þd`˜a?üù?ÿÿÿÿÿÿÿÿÿÿÿÿ혡Wý0Ÿü?GÿÿÿÐÿÿÿÿÿ÷ô€ÿ÷ô€Ñ_ÿøû*€¿ïì GLPoÿûôþÿÿÿÿÿÿÀ€¿ÿߣÿÿÿÿÿÿÿÿÿÿûþÿÿâ›d¶76VÂöp4€×štHDZÁŠi§M~OÿÿÿÿÿÈl÷kØ¥ÿþaÿÿÿÿÿëÿáßÿÿÿá?ãp7ü€€ÿ#þOÿÿÿÿÿÿÿÿÿÿÿÿû_J]ÿ`÷ÿÑÿÿÿßôÿÿÿÿýý ÿýý °—ÿþþË@!ûû*€ùÓ€ÿþýÿ¿ÿÿÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿþÿ¿ÿø§U1•¥Á饜µM¡­•Õ‘¥Ñè€}œ 5ô’UdÀ¥ðS®lÙßÿÿÿÿÿÀ2 ÚÞìÿ§ÿÿÿÿÿùc°¯™CxL0¾þGüŸÿÿÿÿÿÿÿÿÿÿÿÿö¨çÿ©Oþ£ÿÿÿÿÿÿÿÿÿÿÿûú@ÿûú@Yÿü ý•@…÷öU³¦(wÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿñOB#“+›#+qj[c{£Ó›C)û8@k¬L$ô¿A‡àŤËÓ½¾oÿÿÿÿÿ€d5ÛµTRÿÿ(§ÿÿÿÿÿæ@Xò…€‚@:ÀÿäÉÿÿÿÿÿÿÿÿÿÿÿÿÿjOþú”ÿàñú?ÿÿÿÿÿÿÿÿÿÿÿ¿¤ÿ¿¤5‹ÿÿÀŸÙ, ?e;ºb0ÿÿߣÿ÷ÿÿÿÿÿþ"T Wÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿý':²¹1:¹3–¡0¹;²´¶2¹/³¤±dr:Hl"’NIç9‹îÿÿÿÿøChûgnÿòîÿÿÿÿÿ`w’{à$84 Ç@ÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿþ×–:Ó ÿÀôÿÿ÷ý ÿÿÿÿÿHÿÿHkýÿÿ?³ >þËàatÅð8ÿ¿Gÿïÿÿÿÿÿÿÿÿÿÿÿýú?ÿÿÿÿÿÿÿÿÿÿ¿ïÿþ*$Meiningen _gH g³¤‰ø`Bh!N•>w'äÿÿÿÿÿð †·¶± ¿ÿâXÿÿÿÿÿÿ ð¤÷À`pt?üù?ÿÿÿÿÿÿÿÿÿÿÿÿíZ §ý(Ÿü?GÿÿÿÐÿÿÿÿ÷ô€ÿ÷ô€²ÿøû*€·ïìª'LZ§ÿûôþÿÿÿÿÿÿÁOAOÿߣÿÿÿÿÿÿÿÿÿÿûþÿÿâ§Ôg&æ¶gW'BôÖ–âöp4€Õ± GñÕ€@©´§\~ÿÿÿÿÿÈml^³ÿþdÿÿÿÿÿòá’?|F 8ÁØùòÿÿÿÿÿÿÿÿÿÿÿÿÛǯúa?ø~ÿÿþÿ ÿÿÿÿÿïéÿïé ”ÿÿð'ö-Oߨ Θ _ÿ÷èÿýÿÿÿÿÿÿÿÿÿÿÿÿ¿Gÿÿÿÿÿÿÿÿÿÿ÷ýÿÿÅU© ìÄ ìài¬3Ä’d lĹjOûŸÿÿÿÿþÕ¢Õÿü8_ÿÿÿÿÿØA‹ë– B0`ÿò?äÿÿÿÿÿÿÿÿÿÿÿÿÿ´õ‚Ÿô!ðýÿÿÿÿÿÿÿÿÿÿÿßÒ?ÿßÒÿÿàOì ¿²¨]1, ¿ÿïÑÿûÿÿÿÿÿÿTóÿÿ~ÿÿÿÿÿÿÿÿÿÿïûÿÿЏ”Ý]Ø\ QXÚ\™[™×ÙÀÒN}á ¼"»%œÍø?ÿÿÿÿü!²%ª.7ÿýÜ?ÿÿÿÿÿ°8¨Û0 }¡šàÔà?üù?ÿÿÿÿÿÿÿÿÿÿÿÿí#?ÏÿRŸü¿Gÿÿÿÿÿÿÿÿÿÿÿ÷ô€ÿ÷ô€¨ÿøû/€wï쾇LdGÿûôþÿÿÿÿÿÿÿÿÿÿÿÿߣÿÿÿÿÿÿÿÿÿÿÿÿÿÿ⯴çVW&æ&W&röp4€ÔÝèHáæƒ|À‰g}ÿÿÿÿÿÈkk¹ÿþ}ÿÿÿÿÿåŽCê5 †A(°ùòÿÿÿÿÿÿÿÿÿÿÿÿÚ‡Ÿþ¥?ø~ÿÿÿÿÿÿÿÿÿÿÿïéÿïé Lÿð'öA7ߨðΘ‚ÿ÷èÿýÿÿÿÿÿÿ„¸Þÿÿ¿GÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅbŠnŽL.¬M-Ìäìài§«Ø’éoUC°ÒòO2ú‡ÿÿÿÿþÖÖ“ÿü1ÿÿÿÿÿËÿÁwÿþ ~ €ÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿÿÿý«Üÿ­Sÿ€èÿÿÿÿÿÿÿÿÿÿÿþþÿþþÕÿÿcÀ}ýÀp釀<ÿÿ~ÿßÿÿÿÿÿø$$—ÿûôÿÿÿÿÿÿÿÿÿÿßÿüV¨‚êÎæÄêäÎ@@@@@@@@@@@@¾ÎgIÙ0†˜D?*|ò/±ÿÿÿÿÿà U-NX?ÿÆAÿÿÿÿÿû"×<¹€@ˆf¸$Öÿ#þOÿÿÿÿÿÿÿÿÿÿÿÿûEøqÿHÿÑÿÿÿÿÿÿÿÿÿÿÿýý ÿýý ¥÷ÿþþÈ ûûUÓ%€3ÿþýÿ¿ÿÿÿÿÿñXpmÿ÷èÿÿÿÿÿÿÿÿÿÿþÿ¿ÿø®É-•µÁÑ•¸€€€€€€€€€€€€€}œ 4‰¦&âY`¬®D9äSÿÿÿÿÿÀ2¶Úk(ÿ¾7ÿÿÿÿÿö_ù­ÿÿÀAOÍhÿò?äÿÿÿÿÿÿÿÿÿÿÿ€4-ÿ?ýJðDýÿÿÿÿÿÿÿÿÿÿÿßÒ?ÿßÒ<ÿàO삟¿²X 1@ÿÿïÑÿûÿÿÿÿÿÿ ¶ÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€7777 dballe-7.7/extra/bufr/gts-acars2.bufr0000644000175000017500000000025212652630043014442 00000000000000BUFRªN€ Ù 4ÿÿ¬Ä ;)$<€!"Ë@  g B K L % ' M*+,-)>FA!:8FJCYR4RAÿµ,N5ŸÙ&þ„€þÿÖI?ÿÿÿÿþÿÿÿÿÿþC¥5„"`ÿ7777dballe-7.7/extra/bufr/obs1-11.16.bufr0000644000175000017500000000030612652630043014004 00000000000000BUFRÆb€   4 }Ky€@•4aFXDHDE Æy‰*yˆdF€È  Å–A" A"!XDHDE C+ê[ÌŽrÿóŸ¼lxkV³çÐ Ù€o/¾[¡‹€ Ñ£F4hÖ,F6|hÔ&Æ¥V4j±ªÔ«V¬hÑ€7777dballe-7.7/extra/bufr/pilot-ecmwf-geopotential.bufr0000644000175000017500000000032012652630043017406 00000000000000BUFRÐb€[  4[}ÆQ HϦi'ì10954 ÐQ®F4€Á  Á Á ÁE   –A A!JÝûî2¤Ÿ°‘ŸL…ÿþØ<Ÿÿ‚ØÀ£ÿð@bšð€¼hÑ£F4hÑ£F4¸Ñ£K7777dballe-7.7/extra/bufr/obs2-91.2.bufr0000644000175000017500000000065412652630043013736 00000000000000BUFR¬b€[  4[}Ky€M•Te4415614 ¬y±Ìy±ÆF4€Á  Á Á ÁE   –A A!&3ûê[Ì”ÐЛ*¨ß”Àÿüš ÿÿÆ¢ €_ÿøH<È ÿÿ§Fÿá ÜÚÂÿüœ#&ÿÿ–bºÀ¿ÿðªPðÿþIÄ ÿÿÄÃ!/ _ÿøÀU$¸ ÿÿ dBÿàT}ÿü$- ¸Aÿÿ‡á8ˆ?ÿðàú%0ÿþ „ÿÿÇD`}ÿøèŒÄ ÿÿ"Awÿã¡àB/ÿüœ*€ÌB„!B„!B„ hÑ£F4hѥƗ*\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ€7777dballe-7.7/extra/bufr/temp-tsig-2.bufr0000644000175000017500000000051612652630043014547 00000000000000BUFRNb€`   M4`}Êa F¨ÞeÌŒ07650 Na& a$ÆFF€Á ej„‚‚y‚…‚‚K„ „ „ „¶EO¹L$ƒé `eÙŸB@ˆÁ8@(Ê€œàƒ  % W`@À¢À4¨!8$€!À€ Á@ÜhN "hC7P2ø‚?€h'üçÁÀÀËÁ…À‹à„ %€ËàFF’°jh"Ð"‚€AH7pP@$˜ØžÀ LûSPOï)Å*‚@'÷•„,ýÊ@7777dballe-7.7/extra/bufr/synop-old-buoy.bufr0000644000175000017500000000026612652630043015401 00000000000000BUFR¶b€  4}Ky€H[%xÀ€€44613 ¶y‰¾yˆlF€È–A ÉA !LW"‚€õ-æ÷M(cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëäˆ4hÑ£F5›1£F4hÑ£F4hÑ£F7777dballe-7.7/extra/bufr/ecmwf-ship-1-14.bufr0000644000175000017500000000036212652630043015120 00000000000000BUFRòb€  4}ÓM EÅTlièBATFR54 òM*( @€Á$    ????! "%&$–A' A'!`BATFR54 p€ãîši¼;—ÿÿÿü@(´ Zÿÿÿÿÿÿÿÿÿÿÿÿü€cF4hÑ£ 4hÑ£F4hÑ£F4hÑ£F4hÀ7777dballe-7.7/extra/bufr/bufr20000644000175000017500000000026712652630043012565 00000000000000BUFR¶b€  4}Ky€?êËe|x44743 ¶y¶èy´ºF€È–A ÉA !LWc‚€õ-æÏÙÎvIÙ Gÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíˆ4hÑ£F5zñ£MŸ4hÑ£F4hÑ£F7777 dballe-7.7/extra/bufr/synop-strayvs.bufr0000644000175000017500000000037412652630043015362 00000000000000ISID40 LIMV 040900 BUFRäP Ù  ÇV¸ ;¨ ©©§¯¢"¤¯£¤§«$/³‚$jtÂ@”*"¦XIë:âÎÿÿÿøCW{SåÀ €dÿÿÿÄ_ß{àóø.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø­ÿI÷ÿÿïÑÿÀ2?ÿÿÿÿÿü#ÿàÿÿÿàÿü#þÖ€lûûÿýý¿ÿÿÿÿÿÿÿ¿ÿÿÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿþ7777 dballe-7.7/extra/bufr/airep-old-4-142.bufr0000644000175000017500000000024212652630043015014 00000000000000BUFR¢b€Ž 4Ž}Y pn bHUA17 ¢'¼%ôF€Ë–A A!8UA17 ï« ÁF!”€ópQÁ:â¹Ü%Ÿÿÿÿÿà hÑ£F4hÓãF4hÀ7777dballe-7.7/extra/bufr/synop-cloudbelow.bufr0000644000175000017500000000337112652630043016006 00000000000000BUFRôY Ù  ÀÇVÉ,H  ÇF9ÉŒs;b1Xü’aD´\/  !´2±%°¹67»<+0¹<*:¹´¶´±²(6=2·¦´µº¶5°!´:¹0·7»&´¶2¹·»5°*¹º470²&0±2¶"7µ¹°·<(90´0–¦4±:¹*2¶²¶4·!—!:²2µ7»4±²–©7½77»%·¹º2¶74&¼¹¶7»0(2±87²)·2½5·º*¹º470²'¹64±´)»90º7º±´":µ·»0·<%º±´0¹7»4±²&:µ°)²¹0µ!²¹;2·0:&4±0»2$7¶2¹·»&<¹°$7¹0*ª¨ªª«ì€ÀŸRšNtu$(+(¢Iõ»` M͘öö 㡵ï{Zò¦âŠ€ZÞÿ5«ë%^*ˆ’ÊÆ¨Z-'"ú(;)ä©ÌOÿEdncÉ%êÂdúÉCÀ¡ùlC±I‹bî³ÏMâèåÀ®ŠüGrrÌ8Ë$X†lŠWæ—ˆzZW R@9›ReÖŠ%Ønp-´\X(;]‚¼GÄ‹ Ï„ Ë(ÓÑ 6l±'H 3LªÕD¸ôn岋”ûlœ2…¹a@Î@0Š—Gç Ú$iþ Åç´ës½ µ_ûœÕ+ÿ·ýýûÌ!ª3*³5#²¯ *†IH¤Ñ(’PEð!4+ÿ»¿ÿü»¿ÿÿÿÿÿûºîÿîïÿÿÿÀ »ÿÖeà'ÿÿÖ€ÿÿÿÿÿþ¿øÿÿÿý~ÿöÆ8‡ÃŽ:Hºpꂆ^Ó®KI,úxu€ -uñ¥,#ÀÈÜ¥ ¡Ìû%DÏUQEbÏõ‹W”µ"+Ô¥)@ZxðL@ †i_²hŸšk!šk*°Uj ´ð’„l_oС Çú]HÁØb4q`E€•àúô dâ!, KÈúW€ x[X«à¶°¤2GPÂ%‰Â”ÐäÒ1þÿøL›&DÜrdÈ›ÿSqãÄÈÞ)€ÇGqÿáÀQ@ R@øˆ/ÿÿðPT°ƒ`KÀ ð0 àþËHÒ‹@Ã<0 0 0Ã(0SH”ÓM HM4€!”0@åYe–@ÿƒ–Y@` yÀ’ˆ@îîãñàQ!À8áö8ãÿŽ}ö}† –ðl x$/üÿÀù` À:QhØ`÷ÿøÁ÷ÿø}ÿþPÿÿÿÿÿÿÿÿÿÿÿÿÿÿàƒç߸…þÿÿïãþÿÿÿçá¸_ÿÿÿÿÿÿÿÿÿÿßÿÐ/óÿÿÿüÿþÿø  À@ÿÿ x@ð  !ø@ €þ ‰ù|€œù ‚ä.þ_!?Éÿ@“"2b2rˆs' ¨Š€Š†’†‘©)ÿÀÿà?@ü!’8ˆâ†€™(äN¦‡&‘‹ÿÀÿüÿUuUTUP Œ q‡t‘táÔ) ½ý€?ÿÀ@ ÿð– 2ZIÂA2B&䈤 ê+Êx—âøx þÀ Œƒ%Rù¸‚F&É`ádẢbЇ(QAO   (2€>ûÿÿÀtÀ?àpßÿÿÿÿÿÿÿÿÿÿÿÿGÿ•ÿþôàà?øþÿÿüÿð?ÿÀÿÿúÿð?üÿàÿÿþÿø7777 dballe-7.7/extra/bufr/generic-new-repmemo.bufr0000644000175000017500000000024212652630043016340 00000000000000BUFR¢ÈÿÿÔ  .€ÂÀÀÀÁ  +Renrico @P[˜\™]ÈRÞ`3b’6`…À @ 6Ý7777dballe-7.7/extra/bufr/gen-synop.bufr0000644000175000017500000010150012652630043014411 00000000000000BUFR¨b Ç  –A1 A1!n !o¬Œ¤w£Â?÷ê êm™õÿªõšØ¯ñ^¿ôÀÀx}Á2˜JúÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2eÿû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n (o¬Œ¤uRA¥šîu)òÿÿU·Ù'ñô?÷ÀÀxÒQ„F6ÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ‡o¬Œ¤@µBXˆúÊyyòÿÿ#%³WÏñô?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!núo¬Œ¤¸ÈÚ7Ǫu™ìÿÿdý²X'òX?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n%o¬Œ¤JëÚgc úléùÿÿ²ÙOòî?ó ×}B"ð_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n o¬Œ¤…OÂEv*oÿÿÿ–Wgñô?÷À¨xBR˜_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ﬌¤…0‚J™FZ'ÿÿÿŒW·ó„?ó À¥}´"JúÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n o¬Œ¤‚B‚NÄúfD¯ÿÿÿUU¡Wòî?ð™"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿü@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ﬌¤r¢‚<© ögyòÿÿ–M¬×òî?ö@¸¥‘rA…xJ6ÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ﬌¤pPÂ<êªVI?ÿÿÿœXõÜ?ù`± y²ÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿü@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n &o¬Œ¤x ÂBë úkéôÿ‘Õ´Wïñô?ó °¥’"ˆH6ÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ,o¬Œ¤u‚D²ÚÚu©ó?ÿ2Õ¼Yóè?ð¡"yDÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n -o¬Œ¤t–‚Fz–Nxôÿ¯U½W/ñô?ó ‘"yrÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n /o¬Œ¤vèBHvfÞx©òÿ²XÏóè?ð©"yCÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n 1﬌¤wâBJ:Š{9óÿÿ³X'ó„?ð¹"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n 4﬌¤v ‚JôjJ|¹ôÿ Uº×Ÿòî?ð¡"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n 6o¬Œ¤yõ‚NvÚr{)ñÿ}-¹ÖÇñô?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n 7o¬Œ¤wâBOG0b|Iòÿ›-­YOóè?ð¡"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n 9o¬Œ¤ha‚=+ÆþTŸÿÿÿY§òî?ö@Àx¿ÁB JúÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿü@?²eÿû/ì€2eÿû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ;﬌¤knÂ@”* ’Yðÿÿ¬XOòX?ö@© yrÁ@ÈÀ_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n o¬Œ¤iC¡j~2Ÿÿÿÿd­œWWòX?ð©"yCÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n Co¬Œ¤fNBEø`(ëŸÿÿÿFÍuU7÷Ð?ó °0}BÁ"ˆ_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n Io¬Œ¤i–f{Yðÿ¬Xçóè?ö@Á y”ÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n o¬Œ¤GÉÂUýðZ@oÿÿÿZÕ¡VGòî?ð¡"yDÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿü@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ‚﬌¤E—BUG¦&xò?ÿ-UºY'òî?ð¡"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ƒï¬Œ¤?Ú‚SÎ 6/ÿÿÿ<uV·ôL?ó ¸UDA!‚x_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ﬌¤=i‚Pôà¢v©ïÿK}¼Xñô?ó ¸¥‰r!…ðJ6ÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n œo¬Œ¤Ðn{Iò?ÿmºXðú¿ôÀ¸¥’2ðJÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ëo¬Œ¤ ‚IÕö >k)æÿÿ-©ZGñô?ó ÀU¿Á"¨Hr C2ÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿû/ì€2eÿû ¿€døL¿ÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ðo¬Œ¤ cSêúwÉî?ÿ(µZ/ðÈ¿ó ¸UT"¨J!6ÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n!o¬Œ¤2BBø&joùì¿ÿZ­¡X·ðÈ¿ö@À7‰_Á!ÁˆF0  D#ÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2eÿû ¿€døL¿ÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n!o¬Œ¤'í‚B[æqÙêÿ#E¦YWñô?ôÀÀU}¿Á2¨J!6ÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2eÿû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n!*﬌¤câQ„®uÙìÿÿ(•±ÙÇñô?ôÀ¸UÂÁ1‚HF @bÂÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿû/ì€2dËû ¿€døL¿ÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n÷﬌¤ê VVy)æ¿ÿsý²Y_òî?ôÀ¸ACÁèF0¾ ÀbÂÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ¿€døL¿ÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤ßûz8±ðB{)ì¿ÿZM„WÇð´ÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤à ê=làR{)ï?ÿ<…ׯð–¿ð¡"yCÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n o¬Œ¤ê[º?†ªyùðÿÿ<MŒØðá¿ð©"yCP°_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n,o¬Œ¤¼âf*[ÿùÍÿxmŠX?ô°ÿÿàøxÿÿÁ/ðIø  Âÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÿ€ÿü&@?²ÿÿÿÿÿÀÿÿû/ì¿€þû/ì¿ÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤çü*BNà®zYóÿ(­’Ø'ðú¿ñ€°×s…ðLøÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤äRªBuðîxÙñÿÿ(ý˜Øðúð©"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤ã¤úB[æšz™ò?ÿ<Mž×çñô?ð±"yBÁ``_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤áÐ:Bhêr{)ñ¿ÿ<MžØñ?ð©"yBÁPà_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤åóZCïŠR| ó?ÿ2M„×ïð‡ÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤ãê‚D²ÚVz¹òÿÿ<õ‚××ñÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤â}òDJ°¾zYòÿÿAý ×‡ñô?ð©"yBÁP°_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤äRªGÖN|yôÿF•ØWðæ¿ð©"yDÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n-﬌¤æ'jNOÊêzùøÿÿPýwWwð ÿàÏÿÿÿÁŸÁ@_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì¿ÿÿÿû/à?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n.﬌¤âIÒNvÚâ{™øÿÿFUW·ð#ÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n8﬌¤ÚZš;"ðnzIíÿÿPýŸØñ?ð™"yBÁ0_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n-﬌¤¢:FmÉÊÿÿ}MŒX7õÜÿàøUÿÿÁÂ0GøO ¿"ÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿÿÀÿÿû/ì¿€þøì¿ÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n>o¬Œ¤Ü/R>#*ºy9î?ÿ<ŒX'ÿÿÿÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n?o¬Œ¤ØQÂ<¶–bz¹î¿ÿ<ý¤Øoñ?ð™"yBÁ0€_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n@﬌¤Øª?‚º^{ ïÿFý¢ØWðúð©"yBÁP°_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nAo¬Œ¤Þ Z@ÕFN{ÉðÿFýžX_ñ,ÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nA﬌¤Ü/R?ÝàVzùïÿ2M—X7ð×ñ€™"ysÒ F¬ÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?²dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nE﬌¤×µ‚AJvN{ïÿÿAý¡XwðúÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nGo¬Œ¤ÝÐBú¦ziñÿFý X/ñÂ?ð©"yCÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nIo¬Œ¤Ú±RCzZv{ ðÿFM¡X/ðÃÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nI﬌¤ÙV2CÕ€‚{ðÿÿP¢ØñÂ?ñ€±"yrÁÍpLÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nNo¬Œ¤Û“Eø`z{‰óÿFMXðúÿð‰"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿøì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nP﬌¤ÝÐG~{ùõ?ÿ2õŒ×ïñ,¿ð©"yCÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nQo¬Œ¤ÙŠBH:.wÉóÿ7ý Xwò¼?ð™"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nTo¬Œ¤ØîG0à*y õ¿ÿA­œXñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nUo¬Œ¤à êJ1R|Yõ?ÿA­–Øñ,ð±"yC``_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nVo¬Œ¤ÜËšJÍZâxÙõ?ÿ<­X7ñ?ð©"yCP_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nZo¬Œ¤ááªLæ^}Y÷ÿ<­“×ÿñ^ÿö@ÿÿÿÿÁOÂxIøaÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿøÿÿÿÿÿû/à?€þÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n\o¬Œ¤ß‚N5ÀJ}‰÷ÿÿ#­‡Xwð}?ð™"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n2o¬Œ¤üT‚Ofrr9Í?ÿx•‡××òîÿÿàøxÿÿÁÃÈKøúÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?¡eÿÿÿÿÀÿÿû/à?€þÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!ndo¬Œ¤ÕàÂ;WV{ í¿ÿF­¡X·ÿÿÿÿÿà©"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?ÿÿÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nk﬌¤Ó×ê>=6nzIï?ÿ7U¢X7ñÂ?ð™"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!npo¬Œ¤ÒYâ@,N{iï?ÿPýXOñ?ð‘"yBÁ °_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nu﬌¤Ñ›CSJvvYðÿFM§×ßñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nwo¬Œ¤Ï^C¡jZvyðÿÿ-ý¥Øñ?ð‘"yBÁ °_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n{o¬Œ¤ЖšDdºnu©ð¿ÿFU­×ÿñÂ?ð‰"yBÁ°_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n|﬌¤Ö}EëZöy)ò¿ÿF›X/ò¼?ð™"yCÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n~﬌¤Ñ2ÚGJê†{¹ô?ÿK­¡Ø7ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n‚﬌¤Ðb‚Iª–{óÿ<ý¡XoòX¿ð‰"yBÁ`_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n„o¬Œ¤Õ›:I»ê†vÉõ?ÿKM¡XGñÂ?ð‘"yCÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n…﬌¤ÐʪK5†âz©÷ÿKýžØ/ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n†o¬Œ¤×éšKøÖZyIúÿÿi­˜XÿÿÿÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n‡o¬Œ¤Ðb‚LnÚzi÷?ÿF­žØñô¿ð‘"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n7﬌¤ïqÒëàvu9×ÿÿsõˆ×ó ÿÿàø¥ÿÿÁoÅH_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÀÿÿû/à?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nŠï¬Œ¤ÓoÂMJ:xùö¿ÿÿÿýœ×_ñÂÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿÿÿö@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nŒï¬Œ¤ØîMô¦^wøÿK­¢X/ñÂÿó ˜x}C"P_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤Õ›:OÖjz ùÿPý•ØgñÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n‘﬌¤Ò*P €yÙ÷ÿÿ-­›Xòîÿñ€x}BÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n˜o¬Œ¤Î%š;¥&Žx)ì¿ÿ7­¯Øñô?ñ€‰"yrÁɰ_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n˜ï¬Œ¤Ë´š;˜ šyYí?ÿF­¯X?òX?ð™"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n™o¬Œ¤É‚;Ù:âw™ìÿÿKý´X_òî?ñ€‰"yrÊ _ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤Ç²<Рw)ì?ÿKý®Øòî?ð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nžï¬Œ¤ÈsB=â¾tIí¿ÿ(ý®×ÿñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ï¬Œ¤̧Š>ÌpÞx‰îÿÿF­§Øwñ?ð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n¢ï¬Œ¤Æž‚@ð^qyîÿÿP­­ØgñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n§o¬Œ¤ÊäBBÊ&wñ?ÿ7­¨Øoñ?ð‘"yBÁ °_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n§ï¬Œ¤Èþ A ZZuùîÿÿZý°ØoòX?ñ€ˆ×rÁ†à_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n©o¬Œ¤Ë:úBë "wéñÿFý«Xñô?ð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n®o¬Œ¤É‚E5†vòÿ2ý§Xñô?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n²o¬Œ¤Ç‘zGqúÊp©ò¿ÿAMØ'ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n³ï¬Œ¤Ë´šH@þy òÿFM¦Wóè?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n´ï¬Œ¤Ç²H·€~v)ñÿÿF­¦Wïñô?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n¶ï¬Œ¤ÊòJr6Î{ ö¿ÿ2ý¦X§ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n¸o¬Œ¤ÆÒ’K\– .néóÿAM¤Wÿô~?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n¼o¬Œ¤Æ$âNƒà"y‰ö¿ÿ<ý¤WßñÂÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n½ï¬Œ¤ÊòM1V†v õÿÿ2M¨Wgôâ?ð‰"yBÁÐ_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n¾ï¬Œ¤Ë:úMç xYö¿ÿ7M¨×—ó„?ñ€ˆx}BÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n¿o¬Œ¤ÌPÚMô¦Öz©õ¿ÿFý¥W—ô~?ð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÀo¬Œ¤Ë:úNBÆ yùö¿ÿAý£Wïôâ?ñ€ˆx™Bÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÀ﬌¤ÊòNæþyÙöÿ-ý£WÏó„?ð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÂ﬌¤Ë´šNBÆÖw™÷ÿÿÿý§×¿ÿÿÿÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿÿÿö@?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÄ﬌¤È Pe¦Êv ÷ÿ­£XòX?ð‘"yC _ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÆo¬Œ¤ÌÂQ¸0r|™÷?ÿ(ý×ÿòîÿð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÈo¬Œ¤¼Ú‚9÷vöxií¿ÿP¶WÇõÜ?ð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÊo¬Œ¤ÂXÂ8}Ú¦x ìÿÿdýµØ7óè?ñ€˜×BÁ†àFRÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÍo¬Œ¤¾:“¶¦pií¿ÿdý³×¯ôâ?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÑo¬Œ¤¼>B<© N_)í?ÿx­»YOõÜ?ñ€‰"y²ɰ_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÔo¬Œ¤ÀÚ=yæŠu9î?ÿU­¸Xó¶ÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÕ﬌¤»mê?4š^>ÿÿÿ_ŸÖ/ôL?ñ€‰ yrÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n×o¬Œ¤ÂÀê@F ¶oéíÿÿKU¶Wóè?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÙ﬌¤¿K‚AWz Æj©ïÿÿU­¦Xñ^ÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÛo¬Œ¤¼Ú‚B'Ð Þk ïÿÿUý©Ø'ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÛ﬌¤º’A¥šòn™ïÿÿ<­§XÇñ?ñ€‰"yrÁÌ€_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nÞo¬Œ¤¿K‚C®pÞo™ñ?ÿxU£ØÏðúÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nà﬌¤¾DÌæ ÒbYñ¿ÿ#ý¤Øñ^ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nâo¬Œ¤ÂGREª@¾P9ïÿÿZý£×¯ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nâ﬌¤ÂõE·F*ÿÿÿ‡ý™ÖWò¼?ñ€x}BÁ BÚÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!não¬Œ¤óâF,v êk9ñÿÿM­XOñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nåo¬Œ¤Á BGJê ’^éñ¿ÿZý¨W‡ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!næo¬Œ¤½ÞòGÍ Òp™óÿÿU›XOñ^ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!néo¬Œ¤¿šIÈðÂuÙóÿÿ7U¥WÿñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nê﬌¤¾GJ¦Jzréóÿÿ-ý¤Øó ?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!në﬌¤½1:K5†Šrùõ?ÿ(­¥X/ñô?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nío¬Œ¤Ä KëÐæu¹öÿAý£XñôÿÿàÿÿÿÿÁOâ_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿû/à?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nBo¬Œ¤èRâ5ÐoÿùÚ?ÿ‡m‹VÿóRÿÿàù"ÿÿÁÉ_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÿ€ÿü&@?²ÿÿÿÿÿÀÿÿû/à?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nîo¬Œ¤ÂŒÚMŒz~u©ô¿ÿ2MªW×òî?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nðo¬Œ¤¼Ú‚MK`šqÙô¿ÿ#­¡Øñ?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nôo¬Œ¤ºÑ²OG0 Úk¹ó?ÿ­ªØó„?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nõo¬Œ¤Á BNÄúÆv õ?ÿ(ý¨×¿ñÂÿÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nøo¬Œ¤ÂÀêQæVx9õÿ2ý¨WŸóè?ð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nù﬌¤»\zRð° ökYó¿ÿU¢×ÿò&?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nú﬌¤¶‹ê7î  jkùëÿsýµ×÷ôâ?ñ€ˆ¥}rÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nûo¬Œ¤·(*9©VqyíÿKý¹X'õÜ?ñ€¥}r`_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤·R;/ö®tYî¿ÿUM³×ŸõÜ?ôÀ™ y‚ÈÀFTÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤±uÒ;¥& mùïÿ7­ºXôâ?ñ€˜¥rÁ„ˆFTÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€2dËû ?€dÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤²r™ðÿ‡U¬×ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤¬§J Þ*jfiœ¿ÿ_µ^Uwñ,¿ü€À7“ÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤¶R;J¾oùïÿiM¯×¯ñÂÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤µZ= öÎSYìÿÿPý§Vç÷Ð?ñ€‰"yrÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n o¬Œ¤´=Š?Ýà *mðÿÿdU¤WÇò&?ôÀ˜×r1†à_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ﬌¤¶ôA0j ¶bYîÿÿ‡U®×wñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!nDo¬Œ¤ðSšTFªs9Õ?ÿsí‹W‡óè?ÿàø×ÿÿÁ/Åð_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿÿÀÿÿû/à?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤·RBø& ’hYñÿÿ–U XgóR?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤³‚C®p¦:/ÿÿÿ¥­§Õ÷ôâ?ð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤³æÚEú J[ïÿÿ<­¦×¿ó ?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤´ëBF,væ9ÿÿÿiý™Õ×ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüH²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤¸üêFȶ .d¹ñÿÿ­šXgñ,¿ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤¸üêGÚ& bgùîÿÿU£Ø/ÿÿÿÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤³‚GJêv?Oÿÿÿd­¡VWõÜ?ð‰"yBÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüH²eÿû/ì€dËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤±©òGqú N‰ï¿ÿd­ ×¯ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤³æÚI`ÆX ñ?ÿ›­ªW‡ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤º5jI»ê Ziéð?ÿ(­¢ØñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ!ÿü@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤·ç JX* eið¿ÿ7­§XgòX?ÿà"ÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿÿÿì€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤²âjJX* J_éðÿU­±×ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!no¬Œ¤²hÒKÑÆJ;ïÿÿÿi­VgÿÿÿÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n﬌¤´OLæ ^_Yð¿ÿ¯U®×_ñôÿÿàÿÿÿÿÁÿÿø_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n ﬌¤¶ÀL• Ê]Éñ?ÿU©Wòî?ñ€ˆ¥}B _ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙ2ÿü&@?²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777BUFR¨b Ç  –A1 A1!n!o¬Œ¤²hÒLÖ06&ÿÿÿÿxý’Ö·ôâ?ñ€‰"}C¨_ÿÿÿÿâÿÿÿÿÿðøÿÿÿÿÿÿÿÿÿÙÿüL¿²eÿû/ì€dËû ?ÿÿÿÿÿÿÿÿÿÿÿð7777dballe-7.7/extra/bufr/obs1-13.36.bufr0000644000175000017500000000030612652630043014010 00000000000000BUFRÆb€   4 }Ky€E ÈsG¸63112 Æy“Xy’ F€È  Å–A" A"!X63112 ê[ÌØ25§ÿó‹>.Ò ®oãèÿÿÿÁÿÿ÷¾ýz‚€ Ñ£F4hÖ­F6|hÒ¥F4hÑ£F—>|hÑ€7777dballe-7.7/extra/bufr/bufr2.crex0000644000175000017500000000026512652630043013523 00000000000000CREX++ T000103 A001 D08003++ 44743 010 000 0 2004 11 30 12 00 4302 -01245 10084 10084 0016 07 /// //// /// /// /// //// /// // // /// // // //// // // // 2882++ 7777 dballe-7.7/extra/bufr/synop3new.bufr0000644000175000017500000003354612652630043014455 00000000000000BUFRÜb€ 4}¨<H4`gS,16080 Ü<,F€Ç  –A1 A1!n (/µ€u2ÂA£ÞoÉÝ`â‡E¨ÿÿñôLk@˜7•B1Á°H@Hÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4iñ£R«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<H`Rfï16084 Ü<,F€Ç  –A1 A1!n */µ€nùCjm)Üಥõ´ZßòîL'€×r!†H ÿÿÿÿÿüÿÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Ièæg~$16110 Ü<,<€Ç  –A1 A1!n 7/µ€wâBOG0’w)Ýžˆ¥ÏZ·óè‚€ xoB J ëÿÿÿÿÿüÿð hÑ£F4hÏ<›>4hÓcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÂb€ 4}¨<H¿ fbð16134 Â<,F€Ç  –A" A"!T C/µ€f/Eø`(5èHMæ 2jÀ+·øE¦'ðÿýï€ÿÿ€ @1£F4hÑ£K•>TÙñ£P›}XÑ£F\ùñ£7777BUFRÜb€ 4}¨<GÇúf216153 Ü<,F€Ç  –A1 A1!n L¯µ€c!Â>?Ð ¶gIÝ’}E´Ú7óèŒ UB!‚Ð_ÿÿÿÿÿÿÿü_ÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<HŸÌeý`16158 Ü<,F€Ç  –A1 A1!n O/µ€_ÖDþ`ZxIã ’}EÄ['òî‚@¸x™B20H0±ÿÿÿÿÿü?ÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Hã.eG¼16206 Ü<,2€Ç  –A1 A1!n g/µ€T{ÂGp^x‰ä FE¾Z§òX‚ —ÿyB ÇX_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcO«4¸Òã2e.4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<JØe <16230 Ü<,F€Ç  –A1 A1!n s/µ€P“ÂP¦Ànwiàß@_U¿Ûñô‚™ yÂ0ÇX_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÂb€ 4}¨<J@ÊdaD16252 Â<,F€Ç  –A" A"!T ~/µ€FBRPÞA¹€”O±¥€òç«ûù,Aÿýï€ÿÿ€ @1£F4hÑ£K•>TÙñ£P›}XѪÆ•J‘£7777BUFRÜb€ 4}¨<KÌd T16270 Ü<,<€Ç  –A1 A1!n ‡/µ€@µBX†`u‰åŸ`_¥æYoñô‚ ‘†y’! _ÿÿÿÿÿÿÿüÿð hÑ£F4hÏ<›>4hÓcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<IšÆcâP16280 Ü<,F€Ç  –A1 A1!n Œ/µ€>%LÖ0 &lYæ‘n5Ò\ÇñôŒ˜xB20_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<J~Pc2ˆ16310 Ü<.F€Ç  –A1 A1!n ›/µ€3(‚Sò€ &l©çÓ‚õâY÷ñô‚ ƒHyBÁÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Kƒc­”16320 Ü<.F€Ç  –A1 A1!n  /µ€:ÙB\pjyIèQFEÓ[Ïñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Kc‚œ16325 Ü<.F€Ç  –A1 A1!n ¢¯µ€8)ÂXÔ€ry ç_r‘õÛ\ßóè‚@ ¥BA…_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Kªc x16360 Ü<.F€Ç  –A1 A1!n ´/µ€0·‚]Pðrè_Q-UÛZ×ñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<J˜®aÏ16420 Ü<.F€Ç  –A1 A1!n Ò/µ€ñTÅpuÉæŸiUá[ÿñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<InÔa˜`16429 Ü<.<€Ç  –A1 A1!n Ö¯µ€†Kv zy¹é`a_¥Þ\ÿòX‚`™ yrÁ0É8_ÿÿÿÿÿÿÿüÿð hÑ£F4hÏ<›>4hÓcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Joª`¦016480 Ü<.F€Ç  –A1 A1!n ð/µ€ cS}Pv)ç`Ù\ßñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<GÇúcô16522 Ü<.F€Ç  –A1 A1!n!/µ€9ßB>?Ð rkÉê_°»[Oóè‚@ˆU}B_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<H_Xc ô16550 Ü<.F€Ç  –A1 A1!n!/µ€2BBúÀšn©å ’UÔYgóè‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÂb€ 4}¨<I(„gý16021 Â<6A€Ç  –A" A"!T ¯µ€Ñ‚ID %™ó(MèO¸žòÄ+÷øˆ&'ðÿýï€iÿÿ€ @1£F4hÑ£K•>TÙñ£P› ¨Ñ£F\ùñ£7777BUFRÂb€ 4}¨<HßFgßÌ16022 Â<8A€Ç  –A" A"!T /µ€}üÂFú0'…êˆMæ”*â¿+óøB&'ðÿýÿÿ€ @1£F4hÑ£K•>TÙñ£P› ¨Ñ£F\ùñ£7777BUFRÂb€ 4}¨<IS|hQ16033 Â<8F€Ç  –A" A"!T ¯µ€…BJ›àj$Mèo›Ñ¬Óøú¦6@`TÙòåP›•XѪƫR­Z±£7777BUFRÂb€ 4}¨<Gšg´Ô16052 Â<8A€Ç  –A" A"!T /µ€{MB<Р<Á¦Ö¦¯±Œ€ò¥©ãøˆç'ðÿýï€#ÿÿ€ @1£F4hÑ£K•>TÙñ£P› ¨Ñ£F\ùñ£7777BUFRÂb€ 4}¨<Hìòdÿx16168 Â<8F€Ç  –A" A"!T T/µ€O÷‚GgK‰€/ùAØ-où¤ ÀHι@ÿÿ€ @1£F4hÑ£K•>TÙñ£P›•XѪƫR­Z±£7777BUFRÜb€ 4}¨<I/ZeÔ\16172 Ü<8F€Ç  –A1 A1!n V/µ€]EÂIzÐ &g äŸÃ¯ZÏðÈ‚`°U™B"¸J0{ÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÂb€ 4}¨<I…JeÞ 16179 Â<8F€Ç  –A" A"!T Y¯µ€]âL*P:OÉ€ÏáË¢Ú-£ùô é6@`*Ïï€dÿÿ€ @1£F4hÑ£K•>TÙñ£P›•XѪƫR­Z±£7777BUFRÜb€ 4}¨<IS|dÄà16224 Ü<8F€Ç  –A1 A1!n p/µ€LNJ›à jfYå !}õÃ[wñ^R@¸UBRÐDH`ÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Jbødµ@16232 Ü<8F€Ç  –A1 A1!n t/µ€KTSÀòuIáßEâ[§óè‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Iiòdpä16245 Ü<8F€Ç  –A1 A1!n z¯µ€GBKO–w¹å³´UÏ\oòîf@ U…B"@BH` ÆŸÿÿüÿÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÂb€ 4}¨<J¿¾dz¨16258 Â<8F€Ç  –A" A"!T /µ€Gª‚Uýðr>逓ÿÿ²Êé,/ùôAÿýï€ÿÿ€ @1£F4hÑ£K•>ThÑ£P›}XѪÆ•J‘£7777BUFRÂb€ 4}¨<Jë°b«Ä16344 Â<8<€Ç  –A" A"!T ¬/µ€*¼BW]€!" èMðï¨Ã€*ß,øúA H*¾¡@ÿÿ€ @1£F4hÑ£4hÓcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<HKÐcÞh16531 Ü<8<€Ç  –A1 A1!n! ¯µ€=æ‚B^€vyÉéŸásåºÚ§òî‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÏ<›>4hÓcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Hb¯¬16546 Ü<8<€Ç  –A1 A1!n!/µ€*úÂ@°Ð²xéê  ¥¹[GòX‚@ˆU‘BÂ@_ÿÿÿÿÿÿÿüÿð hÑ£F4hÏ<›>4hÓcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<HKÐb~Ø16564 Ü<8F€Ç  –A1 A1!n!/µ€'í‚B^€pÙåŸáŒ…Ë[¿óèR˜xB2C¨_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<G•2g*(16059 Ü<@F€Ç  –A1 A1!n ¯µ€r¢‚<© ¾b9ÝŸó¥žÙ‡ðúÌl€˜x‘¿1èL(Àÿÿÿÿÿÿÿÿÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<GþªgxH16066 Ü<@F€Ç  –A1 A1!n !/µ€w„‚?õP Žg¹Ý_²U¢YïñôLl€Àx›ßR¨P0¢ÿÿÿÿÿüÿÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<HϦgIh16090 Ü<@F€Ç  –A1 A1!n -/µ€t–‚F}0Rr¹Þ #5À[ïòîŒ+@ xrA„ H'ÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<I^:g`Ø16105 Ü<@F€Ç  –A1 A1!n 4¯µ€v ‚JñÐZwéá õ»[—òîl€°¥oa…ˆP!ÿÿÿÿÿü_ÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<IzŒfA¼16149 Ü<@F€Ç  –A1 A1!n J¯µ€dÂKÔ`vwYáòU¥Æ\/ñôÒl€°xÏC0H@„ÿÿÿÿÿü¿ÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<JœcÔ¤16289 Ü<@F€Ç  –A1 A1!n ¯µ€=JBPôàbt©ç 0FUÔÚŸòX‚@¸×}Br_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<JÝ bWÈ16362 Ü<@F€Ç  –A1 A1!n µ/µ€%|‚VèP~xIå^ø#õÖZ/ñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<I©laË(16405 Ü<@<€Ç  –A1 A1!n ʯµ€²‚MK`–y‰é_a ¥Ý\Oñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÏ<›>4hÓcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<JgÚa@|16460 Ü<@F€Ç  –A1 A1!n æ/µ€ÂS>Іxùèß`‚õÑ\Oñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<GÒ¸c©¬16520 Ü<@<€Ç  –A1 A1!n!/µ€:šÂ>•Àây)ìŸÃnU²Úïòî‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÏ<›>4hÓcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<HÞbœ$16560 Ü<@F€Ç  –A1 A1!n!/µ€)ÂB@þðVz)ê_Ò›E»Zóè‚ U…B¸BHfÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<H]dg‚ 16076 Ü<FF€Ç  –A1 A1!n &/µ€x ÂBë öfIß`ƒx•§ÚgñôLl€Àx›ßB0N0„ÿÿÿÿÿü?ÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Iv¤dŠH16239 Ü<FF€Ç  –A1 A1!n w¯µ€H¤‚Kµ æqÙåŸònEÌ\ñ^Ò€ÀUŸß2BèJ0uÿÿÿÿÿÿÿÿÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<KrcÅ16312 Ü<FF€Ç  –A1 A1!n œ/µ€4jcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<IO”g~$16099 Ü<FF€Ç  –A1 A1!n 1¯µ€wâBJ| žvéâ_c#E¼[/ñô’g€© yrPÉ8_ÿÿÿÿÿÿÿü_ÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÂb€ 4}¨<Gg 16061 Â<ÀF€Ç  –A" A"!T ¯µ€pPÂ<èZD €ŒpÀzǬGúî¦&@`TÙñ£P›•XѪƫR­Z±£7777BUFRÜb€ 4}¨<L–rb!16643 Ü< F€Ç  –A1 A1!n!A¯µ€"‚d³RyÉè_DÎ[÷ñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<M7”bæ\16648 Ü< F€Ç  –A1 A1!n!D/µ€.eÂi¼ ju)éߣÛZ_ñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<NÀbet16684 Ü< <€Ç  –A1 A1!n!V/µ€&WBp²wiä_r•ä\?ñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÏ<›>4hÓcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<MmJc”016622 Ü<F€Ç  –A1 A1!n!7/µ€9CkjPRyÉèßÜZWñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<LCpbäh16641 Ü<F€Ç  –A1 A1!n!@¯µ€.F‚b€Ryyæß‘Í[¯ñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<LÈ@a˜`16682 Ü<F€Ç  –A1 A1!n!U/µ€†fBzyiéßÄZ÷ñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<M·‚a”x16716 Ü<F€Ç  –A1 A1!n!f/µ€G‚m¼~xäŸ8å[wñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>\ªcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<Mݘ_»Ð16746 Ü<F€Ç  –A1 A1!n!u/µ€û½nìÀžmùã_ƒ‡¥Ö\/ñô‚ÿÿûßÿÿø_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcO«5XÑ£R©R4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<IΈgŸX16108 Ü<Ž<€Ç  –A1 A1!n 6/µ€yõ‚Nt@rw¹ãŸÃ(¥Á[_ñô‚@˜x²2 Nëÿÿÿÿÿü_ÿð hÑ£F4hÏ<›>4hÓcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<I[LffØ16148 Ü< @F€Ç  –A1 A1!n J/µ€fm‚JÚ`jvÙÞ__•Ã\óè‚™†y²Á0Ê(_ÿÿÿÿÿÿÿüÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÂb€ 4}¨<H®rhTü16008 Â<"¶F€Ç  –A" A"!T /µ€…OÂEsxMãRª€¢È«çø2†6@`*Ëï€ ÿÿ€ @1£F4hÑ£K•>TÙñ£P›•XѪƫR­Z±£7777BUFRÜb€ 4}¨<IGÄg„16098 Ü<-Ú<€Ç  –A1 A1!n 1/µ€x@J> úu9áD#¥¿['òîŒ&@¡ yr@É8_ÿÿÿÿÿÿÿüÿð hÑ£F4hÏ<›>4hÓcR«5XÕjU«V4hÑ£F4hÑ£F4`7777BUFRÜb€ 4}¨<JØcš 16294 Ü4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777dballe-7.7/extra/bufr/gts-acars-us1.bufr0000644000175000017500000000021012652630043015060 00000000000000BUFRˆ8€  ÿÿ¬Ä ;ÁAÁBË !!C † ë:KRXCOOBAFJCYR4RA!ÒšÂì“ FÎiRÆÁü†\66Õÿÿÿûÿƒø?ƒø?€7777dballe-7.7/extra/bufr/temp-bad2.bufr0000644000175000017500000000144612652630043014255 00000000000000BUFR&b€e 4e}±XMÌþj¬˜33393 &X5ÈF.€É–A A!—A A—ÿ¦BÄŽíŠÀª²`›™üÓþ ˆ?üŽq&ïÿÿÿÿÿÍ›Rµ "©2©®™ê€Qð/ÿÿÿÿýd¢ÿÿÿÿÿ¢D&ˆé´wFô €H !*Šh£ÿÿïPÑÑmÿÿýÈ@_ÿÿÿÿúÈ#6°ˆã@3ŸEf¦‚mgÖnÿþÊÐ@x¬üÍOÿÿ×ÿÿÿÿÿ‡b¾dÓg,ÿÿN!Yv^eþ ‰tÿÿÿÿÿ¾„a _ÿÿÿÿ÷¨–@€8› þú£uÿÿÿÿßB¼c/ÿÿÿÿûüW‹¸@#‡ÿ} aÅ?ÿð·ÿï¡,' Ÿ~ÿýôœÿÿÂïÿÿÿü‹`_ÿÿÿÿ÷ÐU €Zyÿ aÿÿÿÿà.â¢DFÿü …F ÿÿ‰Ÿÿÿÿø‡¿ÿðïÿðàF¡øú þ&Á^ #xCßÿÌ@ðDóhÿúPº ÿÿÿÿÿJ€cÂÿâoÿÿÿþÃÀ8p0gp‡8 Bç\ @b¿4hÑ£F4hÑ£F.4hÑ£F5(Ò£F\hѥƔiQ£F.4hÑ¥Æ4¸Ñ£R*4hÑ¥Æ4¸Ñ£F—4iq£FJ4¨Ñ£F—4iq£F¥ThÑ¥Æ\hÑ©F4iñ£FJ4hÑ£K\hÑ©F4iq£F¥4hÑ¥Æ>4hÑ©F4jQ£F”hÑ£F—4iq£„ÿÿþýûÿÿß¿ýû÷ÿß¿ÿýÿÿïÿ¿ÿýÿ÷ÿÿ¿~ÿÿÀ‚€ÀM ,À&H0’ ¡wƒlÁâa20²Ðq$Fò'Ù™ ‡Æänây7777dballe-7.7/extra/bufr/temp-bad5.bufr0000644000175000017500000000177612652630043014266 00000000000000BUFRþÿÿÿe ۀɖA A!À (ûí Wôiföÿüy?ýJv¨ÿú´ª N €sZœ2©¼‚ÿëJ²ÿÿÿ7@OÿýiV_ÿÿæ> ÿÿ® ¤ÿÿü[ÿÿÿÿ ѨjPïÜÿÿÔ-?ÿýô?ÿÿÿÿòø=ô ÿÿÿÿþ_7¥‚ÿéîÿþðPOÿý;ÌÿÿÝØ ÿÿ§zÿÿû®?ÿôÛC¿ÿÿp¨'ÿþ”çÿÿíòÿÿÒ|}ÿÿýµ„€ÑªKø¶ˆÿÿIs/ÿÿö¸ÿèþvÿÿþÖ°/ÿÿÿÿùh Ùª ÿÿ¢ZÿÿûÁ?ÿô?ÿÿ]Àÿÿÿÿüæ+Ÿÿÿÿÿÿ›‚-s@Ÿÿùéžÿÿ®ÿÿ=s}ÿÿõu‚ÿç>iÿþ¬0OÿüèÈïÿÿÕ^ÿÿÿÿÿ/…¢–?ÿóo.?ÿÿN!Zâe䤴 ÿÿË|Iÿÿý _ÿÿÿÿòП øÿÿ)ðçÿÿô‚ÿå&'ÿÿþ}åì–ÆIhRO– ÿÿ’ØÓÿÿùáA?ÿò7 ?ÿÿ7 'ÿþ=aÿÿæTÿÿÿÿÿ™´½`Ÿÿø¥€_ÿÿ—p€H3piB· ÿâMúL‚@P /ÿÿÿÿù|9ÉÄ@(•‰w»2éA?ÿñ6ñ¿ÿÿ!˜ÿÿÿÿý D ÿÿÿÿÿ›€Ì€_ÿÿÿÿóH €\5îª_ñ½ÿâ•Öÿÿþ6°/ÿÿÿÿú€EÜ@51ˆ—I‡øª¿ÿÿÿÿïP3Øÿÿÿÿýêb]ÿÿÿÿÿÈ€ÌA _ÿÿÿÿøH‡Ð˜~) .W0äÿÿÿÿé@fh/ÿÿÿÿüLBüÿÿÿÿÿp˜Y@¿ÿÿÿÿïð3 ñ†Ü¥ê!X‚ÿÿÿÿÿ¼ 'Ð_ÿÿÿÿø „šÿÿn/ÿÿð’ÿÿÿÿÚàØ/ÿÿÿÿû„‚'ÿÿÿÿÿŽƒB@¿ÿÿÿÿó`{ÿÿÿÿþ€ ú 'ÖÂk‹Ð\`_ÿÿÿÿù؃„ ÿÿÿÿÿgÿá¥Êÿþ h/ÿÿÿÿýAÿÿÿÿÿ¢˜-?ÿð¢ãÿÿ±oÆ܆& t„ÿÿÃ{—ÿÿü „ZØ[rXè@ÿÿ .7ÿÿð%/ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü7777dballe-7.7/extra/bufr/wmo-ship-1.bufr0000644000175000017500000000040012652630043014370 00000000000000BUFRN€ Ù ÿÿ¬’  €„È „A…¶ÕŒVÈ<µà?¾û>^dzÀ÷^‘ÿÿÿÿÿÿÿÿ@÷¾žŸÿÿÿÿí­ÿÿÿÿÚíÿÿÿÿÿÿùôÿÿÿÿÿÿÿÿÿ¯à{ø2ù=O(ÿÿÿÿÿÿÿÿÿÿÿ‡ÿÿÿìCÿÿÿÿÿÿÿÿÿüL`åÎ ç?ÿÿÿÿÿÿÿÿÿÿð?ÿá|?ÿÿÿÿÿÿÿþ”Ê’Ãÿÿÿÿánÿÿÿÿÿÿÿþ”’7ÿÿÿÿáe¿ÿÿÿÿÿÿÿþ”Ê’Kÿÿÿÿá^¿ÿÿÿÿÿÿÿþ˜²“;ÿÿÿÿáRÿÿÿÿÿÿÿþ™”SÿÿÿÿáJ?ÿÿÿÿÿÿÿþ¢Ú—ëÿÿÿÿáBßÿÿÿÿÿÿÿþ ‚—#ÿÿÿÿá@ßÿÿÿÿÿÿÿþ£*˜;ÿÿÿÿá:ÿÿÿÿÿÿÿþ¢Š—›ÿÿÿÿá6Ÿÿÿÿÿÿÿÿþ¥‚—sÿÿÿÿá/ÿÿÿÿÿÿÿÿþ£¢”Ëÿÿÿÿá'_ÿÿÿÿÿÿÿþ¥2’sÿÿÿÿá¿ÿÿÿÿÿÿÿþ«r’sÿÿÿÿá_ÿÿÿÿÿÿÿþª2‘ûÿÿÿÿáÿÿÿÿÿÿÿþ®j’Kÿÿÿÿáÿÿÿÿÿÿÿþ®j’Kÿÿÿÿà@q_ÿÿÿÿÿÿÿÿÿÿÿþðOÿà@kÿÿÿÿÿÿÿÿÿÿÿÿ¯ÿà@e?ÿÿÿÿÿÿÿÿÿÿÿÿ/ÿà@_ÿÿÿÿÿÿÿÿÿÿÿþªïÿà@YŸÿÿÿÿÿÿÿÿÿÿÿþ´oÿà@TŸÿÿÿÿÿÿÿÿÿÿÿþÜ/ÿà@Oßÿÿÿÿÿÿÿÿÿÿÿþ×oÿà@K?ÿÿÿÿÿÿÿÿÿÿÿþ-Oÿà@Fÿÿÿÿÿÿÿÿÿÿÿÿþ/ÿà@B¿ÿÿÿÿÿÿÿÿÿÿÿþUÏÿà@>ßÿÿÿÿÿÿÿÿÿÿÿþdÏÿà@;_ÿÿÿÿÿÿÿÿÿÿÿþ‡oÿà@4¿ÿÿÿÿÿÿÿÿÿÿÿþŒ/ÿà@1¿ÿÿÿÿÿÿÿÿÿÿÿþAoÿà@,ÿÿÿÿÿÿÿÿÿÿÿþiïÿà@&ÿÿÿÿÿÿÿÿÿÿÿÿþPoÿà@ ÿÿÿÿÿÿÿÿÿÿÿþZ/ÿà@ßÿÿÿÿÿÿÿÿÿÿÿþ< ÿà@¿ÿÿÿÿÿÿÿÿÿÿÿþPÀ Mâc+; ›ƒIrù>ù¶À€N¤Ð9àhÿÿÿÿÀÿÿÿÿÿÿüÿø@ïÿÿÿÿÿÿÿÿ¤°£Rÿÿÿÿø@ÿÿÿÿÿÿÿÿ¤Ø£Hÿÿÿÿø@oÿÿÿÿÿÿÿÿ¦¸¤’ÿÿÿÿø@ÿÿÿÿÿÿÿÿ¦®£Àÿÿÿÿø@Ÿÿÿÿÿÿÿÿÿ¨è£pÿÿÿÿø@×ÿÿÿÿÿÿÿÿ¨À£ÿÿÿÿø@'ÿÿÿÿÿÿÿÿ©.£Rÿÿÿÿø@ oÿÿÿÿÿÿÿÿ¨Ô¢øÿÿÿÿø@ 7ÿÿÿÿÿÿÿÿ©V£zÿÿÿÿø@ ¿ÿÿÿÿÿÿÿÿ¨Ô¢øÿÿÿÿø@gÿÿÿÿÿÿÿÿª £Êÿÿÿÿø@Ÿÿÿÿÿÿÿÿÿ«¤’ÿÿÿÿø@‡ÿÿÿÿÿÿÿÿ«¤œÿÿÿÿø@'ÿÿÿÿÿÿÿÿªú¤ˆÿÿÿÿø/ÿÿÿÿÿÿÿÿÿÿÿÿºÀûÿøŸÿÿÿÿÿÿÿÿÿÿÿÿÄÀûÿøÿÿÿÿÿÿÿÿÿÿÿÿ¨?ÿøïÿÿÿÿÿÿÿÿÿÿÿÿ´€Ïÿø?ÿÿÿÿÿÿÿÿÿÿÿÿµÁwÿøOÿÿÿÿÿÿÿÿÿÿÿÿÀÏÿøïÿÿÿÿÿÿÿÿÿÿÿÿËÿøÿÿÿÿÿÿÿÿÿÿÿÿ™Ïÿø¯ÿÿÿÿÿÿÿÿÿÿÿÿ›_ÿø'ÿÿÿÿÿÿÿÿÿÿÿÿž7ÿøwÿÿÿÿÿÿÿÿÿÿÿÿ–€ÏÿøOÿÿÿÿÿÿÿÿÿÿÿÿ•@çÿø¿ÿÿÿÿÿÿÿÿÿÿÿÿž‹ÿø?ÿÿÿÿÿÿÿÿÿÿÿÿ–Kÿø GÿÿÿÿÿÿÿÿÿÿÿÿŸAÿø ÿÿÿÿÿÿÿÿÿÿÿÿÿœÀçÿø ?ÿÿÿÿÿÿÿÿÿÿÿÿŒKÿø Çÿÿÿÿÿÿÿÿÿÿÿÿ‘ïÿø Ïÿÿÿÿÿÿÿÿÿÿÿÿ›‚Wÿøÿÿÿÿÿÿÿÿÿÿÿÿ‘ƒ#ÿø'ÿÿÿÿÿÿÿÿÿÿÿÿ’ÂÔ êÊäèÞ@ ä¢>O¾m°`÷õ;@³ÿÿÿÿð?ÿÿÿÿÿÿÿþ'ÿÿÿÿÿÿÿÿé1)(ÿÿÿþ»ÿÿÿÿÿÿÿÿée©3¿ÿÿÿþkÿÿÿÿÿÿÿÿé•)J?ÿÿÿþ[ÿÿÿÿÿÿÿÿéΩ^?ÿÿÿþ!ÿÿÿÿÿÿÿÿ騩h?ÿÿÿþëÿÿÿÿÿÿÿÿê ©t¿ÿÿÿþÿÿÿÿÿÿÿÿêX)w?ÿÿÿþwÿÿÿÿÿÿÿÿêU©O?ÿÿÿþùÿÿÿÿÿÿÿÿê”)B¿ÿÿÿþÏÿÿÿÿÿÿÿÿêé)L¿ÿÿÿþ“ÿÿÿÿÿÿÿÿêÆ)B¿ÿÿÿþ{ÿÿÿÿÿÿÿÿêë©B¿ÿÿÿþ«ÿÿÿÿÿÿÿÿÿÿÿÿðÿþEÿÿÿÿÿÿÿÿÿÿÿÿî`ÿþãÿÿÿÿÿÿÿÿÿÿÿÿï2ÿþ‰ÿÿÿÿÿÿÿÿÿÿÿÿòpÿþ7ÿÿÿÿÿÿÿÿÿÿÿÿä°ÿþMÿÿÿÿÿÿÿÿÿÿÿÿëZÿþÿÿÿÿÿÿÿÿÿÿÿÿÿìÐ ÿþ»ÿÿÿÿÿÿÿÿÿÿÿÿáÿþyÿÿÿÿÿÿÿÿÿÿÿÿä°2ÿþ=ÿÿÿÿÿÿÿÿÿÿÿÿä<ÿþ—ÿÿÿÿÿÿÿÿÿÿÿÿç0 ÿþ5ÿÿÿÿÿÿÿÿÿÿÿÿæàŒÿþ ÿÿÿÿÿÿÿÿÿÿÿÿä°ŒÿþÝÿÿÿÿÿÿÿÿÿÿÿÿä°´ÿþkÿÿÿÿÿÿÿÿÿÿÿÿåP¾ÿþ ÿÿÿÿÿÿÿÿÿÿÿÿä`Èÿþ‰ÿÿÿÿÿÿÿÿÿÿÿÿæ@¾ÅC&°±º0· “ï›k¨Ææƒžsà†ÿÿÿÿüÿÿÿÿÿÿÀÿÿ„¨ÿÿÿÿÿÿÿÿúMŠ4ÿÿÿÿ„hÿÿÿÿÿÿÿúU 8ïÿÿÿÿ„;ÿÿÿÿÿÿÿúuŠ=Oÿÿÿÿ„ÿÿÿÿÿÿÿúŠ:Ïÿÿÿÿ„ÿÿÿÿÿÿÿúyê2ÿÿÿÿ„ÝÿÿÿÿÿÿÿÿúÊ5/ÿÿÿÿ„±ÿÿÿÿÿÿÿú›ª:Ïÿÿÿÿ„—ÿÿÿÿÿÿÿúšj9ÿÿÿÿÁÿÿÿÿÿÿÿÿÿÿÿÿü$¿ÿ›ÿÿÿÿÿÿÿÿÿÿÿÿýP¿ÿ‚ÿÿÿÿÿÿÿÿÿÿÿÿøP ÿÿqÿÿÿÿÿÿÿÿÿÿÿù¸¿ÿUÿÿÿÿÿÿÿÿÿÿÿú¼"ÿÿQÿÿÿÿÿÿÿÿÿÿÿúä ÿFÿÿÿÿÿÿÿÿÿÿÿû˜ÿ>ÿÿÿÿÿÿÿÿÿÿÿÿûÀ ÿÿ8ÿÿÿÿÿÿÿÿÿÿÿÿü°ÿÿ'ÿÿÿÿÿÿÿÿÿÿÿÿø´ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿøð?ÿÿÿÿÿÿÿÿÿÿÿÿÿù@!¿ÿúÿÿÿÿÿÿÿÿÿÿÿÿù¸ÿÿóÿÿÿÿÿÿÿÿÿÿÿÿù¿ÿáÿÿÿÿÿÿÿÿÿÿÿÿùô!¿ÿÒÿÿÿÿÿÿÿÿÿÿÿÿùà"ÿÿÉÿÿÿÿÿÿÿÿÿÿÿù¿ÿ®ÿÿÿÿÿÿÿÿÿÿÿù|2?ÿ—ÿÿÿÿÿÿÿÿÿÿÿùT.@1]iŽ­¬M,$-!j#äûæÚÖ+Ý è4¹?ÿÿÿÿÿÿÿÿÿÿðŸÿáqÿÿÿÿÿÿÿÿþ“Ú‘ûÿÿÿÿá`?ÿÿÿÿÿÿÿþ“²‘çÿÿÿÿáVÿÿÿÿÿÿÿÿþ–‚’›ÿÿÿÿáQŸÿÿÿÿÿÿÿþ›2”+ÿÿÿÿáA¿ÿÿÿÿÿÿÿþ¡"—Ãÿÿÿÿá6?ÿÿÿÿÿÿÿþ ª—Kÿÿÿÿá-¿ÿÿÿÿÿÿÿþ¦Â—ëÿÿÿÿá"Ÿÿÿÿÿÿÿÿþ¦š”£ÿÿÿÿá¿ÿÿÿÿÿÿÿþ­”ÿÿÿÿá?ÿÿÿÿÿÿÿþ­*“cÿÿÿÿáÿÿÿÿÿÿÿþ«š“cÿÿÿÿà@y?ÿÿÿÿÿÿÿÿÿÿÿþÃOÿà@r?ÿÿÿÿÿÿÿÿÿÿÿþ›ÿà@k_ÿÿÿÿÿÿÿÿÿÿÿþÿà@dŸÿÿÿÿÿÿÿÿÿÿÿÿTïÿà@^?ÿÿÿÿÿÿÿÿÿÿÿþs/ÿà@XŸÿÿÿÿÿÿÿÿÿÿÿþ–/ÿà@Sÿÿÿÿÿÿÿÿÿÿÿþ¯Oÿà@N_ÿÿÿÿÿÿÿÿÿÿÿþðïÿà@I¿ÿÿÿÿÿÿÿÿÿÿÿþ#oÿà@EÿÿÿÿÿÿÿÿÿÿÿþFïÿà@AÿÿÿÿÿÿÿÿÿÿÿþA/ÿà@6ÿÿÿÿÿÿÿÿÿÿÿþi ÿà@-ÿÿÿÿÿÿÿÿÿÿÿþZ ÿà@_ÿÿÿÿÿÿÿÿÿÿÿþP WŠ# ³ y KZˆù>ù¶½ÀJü:?Ÿ¯ÿÿÿÿÀÿÿÿÿÿÿükÿø@oÿÿÿÿÿÿÿÿ¤ì¤ÿÿÿÿø@‡ÿÿÿÿÿÿÿÿ¥x¤¦ÿÿÿÿø@'ÿÿÿÿÿÿÿÿ¤¦¤tÿÿÿÿø@?ÿÿÿÿÿÿÿÿ¥<¤ÿÿÿÿø@Oÿÿÿÿÿÿÿÿ§v¥Pÿÿÿÿø@?ÿÿÿÿÿÿÿÿ§X¥–ÿÿÿÿø@çÿÿÿÿÿÿÿÿ§Ð¥ªÿÿÿÿø@·ÿÿÿÿÿÿÿÿ¨˜¦ÿÿÿÿø@ _ÿÿÿÿÿÿÿÿ¨z¥Œÿÿÿÿø@ _ÿÿÿÿÿÿÿÿ©~¥–ÿÿÿÿø@çÿÿÿÿÿÿÿÿ©ì¤¦ÿÿÿÿø@ÿÿÿÿÿÿÿÿÿ«|¤tÿÿÿÿø‡ÿÿÿÿÿÿÿÿÿÿÿÿª€£ÿø7ÿÿÿÿÿÿÿÿÿÿÿÿ¤@{ÿø÷ÿÿÿÿÿÿÿÿÿÿÿÿ@SÿøÇÿÿÿÿÿÿÿÿÿÿÿÿ×€Ëÿø‡ÿÿÿÿÿÿÿÿÿÿÿÿ…Ëÿø7ÿÿÿÿÿÿÿÿÿÿÿÿ›“ÿøÿÿÿÿÿÿÿÿÿÿÿÿ¦ÁãÿøÿÿÿÿÿÿÿÿÿÿÿÿÿºÀËÿøÿÿÿÿÿÿÿÿÿÿÿÿÿ@Ëÿøÿÿÿÿÿÿÿÿÿÿÿÿ‘ãÿøOÿÿÿÿÿÿÿÿÿÿÿÿ‘‚ ÿø ÷ÿÿÿÿÿÿÿÿÿÿÿÿšBûÿø ·ÿÿÿÿÿÿÿÿÿÿÿÿ’ÃÃÿøgÿÿÿÿÿÿÿÿÿÿÿÿ—Ãè7777dballe-7.7/extra/bufr/obs1-19.3.bufr0000644000175000017500000000030612652630043013730 00000000000000BUFRÆb€  4}Y€Tœ(P‘VRZO2 Ƙd–F€È  Å–A" A"!XVRZO2 C€ëêÈ,Jµ'ÿóœ< ,l ¼ïçЀA!®û^ýìÀ Ñ£F4hÑ£F6|hÔ&Æ¥V4j±ªÔ«V¬hÑ€7777dballe-7.7/extra/bufr/obs1-9.2.bufr0000644000175000017500000000030612652630043013646 00000000000000BUFRÆb€   4 }Ky€Gû¼mÉxDFPC Æy€y€ØF€È  Å–A" A"!XDFPC ÿÿëê[ÌÁ²M·ÿóâÿþ´ŠÜ­ÏÿÿÿÿÿÁÿÿ÷¾WgÿÿÀ Ñ£F4hÖ­F4hÒ¥F4hÑ£F—>|hÑ€7777dballe-7.7/extra/bufr/test-airep1.bufr0000644000175000017500000000024212652630043014631 00000000000000BUFR¢b€  4}Ky€Mx¯n EU4824 ¢yŠ”yˆj €Ë–AÉA!8EU4824 ©o0àP¢kÅw@þáð0ÿÿÿÿÿà hÑ£F͘Óã<ÿÿÿà7777dballe-7.7/extra/bufr/synop-oddgust.bufr0000644000175000017500000001105412652630043015315 00000000000000BUFR,N  €ÇP¤2¶3·¶0·2/³¬ß÷B=g|ÈøMÿ8KÕÿÿÿÿøCm«i¿ÿñôÿÿÿÿÿ`wqûà$8C ÆÀÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿõ)ÿÀôÿÿÿÿÿÿÿÿÿÿÿHÿÿHÿÿÿÿ?²€ ~þʘ|D°Nÿÿ¿Gÿïÿÿÿÿÿü$Œ$ƒÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿÿþ(List auf Sylt gX ÔX$}úˆ!H¨›ÒqG–?ÿÿÿÿ𠆿6¼¼?ÿáÿÿÿÿÿÿ'þ ¿ÿðcð\?üù?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿé×ÿ„ü?Gÿÿÿÿÿÿÿÿÿÿÿ÷ô€ÿ÷ô€ÿÿÿøû Ÿïì‚GÄAÿûôþÿÿÿÿÿÿÀu€uÿߣÿÿÿÿÿÿÿÿÿÿûÿÿÿâ‚566†ÆW7v–röp5€ÜˆšHN¯)Á ¼g,z#ÿÿÿÿÿÈkékºÃÿþÏÿÿÿÿÿòàÒ_|Ç€ÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ?óÿÀôÿÿÿÿÿÿÿÿÿÿÿHÿÿHÿÿÿÿ?²0>þÉ`8|D`ÿÿ¿Gÿïÿÿÿÿÿüÿýú?ÿÿÿÿÿÿÿÿÿÿ¿ÿÿþ(7Fehmarn _gX ÈŽ¤Ž&8|õœÚt™¿ÿÿÿÿð †Æ¼?ÿâXÿÿÿÿÿÿ ð £÷À`a?üù?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿã×ÿ0Ÿü?Gÿÿÿÿÿÿÿÿÿÿÿ÷ô€ÿ÷ô€ÿÿÿøû#ÿï삇Ä<gÿûôþÿÿÿÿÿÿÀëë?ÿߣÿÿÿÿÿÿÿÿÿÿûÿÿÿâ‰4†Ö'W&rÔgV†Ç6'VWGFVÅöp5€Û+lHy¶ÁiÈ'2zãÿÿÿÿÿÈl‰kà³ÿþ2ÿÿÿÿÿòâ:?|ÆÀÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿþó ÿÀôÿÿÿÿÿÿÿÿÿÿÿHÿÿHÿÿÿÿ?²0 ¾þÉ`E|D°)ÿÿ¿Gÿïÿÿÿÿÿü4ÿýú?ÿÿÿÿÿÿÿÿÿÿ¿ÿÿþ(¢Schwerin _gX ²ðD$°#ÜE›Út—²?ÿÿÿÿð †Áµ[ÿâ¼ÿÿÿÿÿÿ ðã÷À``þ?üù?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿãÇÿ0Ÿü?Gÿÿÿÿÿÿÿÿÿÿÿ÷ô€ÿ÷ô€ÿÿÿøû#{ïìŒÄKÿûôþÿÿÿÿÿÿÿÿÿÿÿÿߣÿÿÿÿÿÿÿÿÿÿûÿÿÿâ‹„w&V–g7vÆBöp5€Ûà4IÇsö€ýù×§fy£ÿÿÿÿÿÈlk$«ÿþ0Ÿÿÿÿÿÿëãïÿÿÿ`ÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿýÿÀ³ôÿÿÿÿÿÿÿÿÿÿÿHÿÿHÿÿÿÿ?²0 þþÉ`Y|D°,ÿÿ¿GÿïÿÿÿÿÿüSÐ@—ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿÿþ(ÈEmden _gX ¬·Äv¾@œp®?ÿÿÿÿð †âÖÕÚÿÿåÜÿÿÿÿÿþXìfP  D€ÚŒ/€ÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿü*ÿâÿ×èÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿÿe$ýý’ÀÎø‰`nÿÿ~ÿßÿÿÿÿÿøŸ(fßÿûôÿÿÿÿÿÿÿÿÿÿÿÿüQÀ„äÊÚÊÜ@@@@@@@@@@@@@@¾Î°H° ® ? ©8ìäotÿÿÿÿà ¬­’µÿÿÉaÿÿÿÿÿýÌ)F·€`ˆáH#Pâ`ÿäÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ùŒÿàú?ÿÿÿÿÿÿÿÿÿÿÿ¿¤ÿ¿¤ÿÿÿÀŸÙ@e">"X¿ÿߣÿ÷ÿÿÿÿÿþ ’ eÿþýÿÿÿÿÿÿÿÿÿÿßÿÿÿ‡'2º¹:¸84·³¬ÐsLg¸±NM:ëÓÿÿÿÿøCc[[-?ÿñûÿÿÿÿÿÿ“ÿ_ÿø1ø’þGüŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿÿïþ£ÿÿÿÿÿÿÿÿÿÿÿûú@ÿûú@ÿÿÿü ý@O÷ö<#â ?ÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿñJ’C ss{³+‘û8Àl±Z$-´A`”Ýs™½ñÿÿÿÿÿ€d6ä¶Éÿÿ>‡ÿÿÿÿÿöA#~‚# a¸†Uÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿêSÿ€èÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿÿePýý–€‚øŠ Iÿÿ~ÿßÿÿÿÿÿøh0hÿûôÿÿÿÿÿÿÿÿÿÿÿÿÿüRÒšÂÎÈÊÄêäÎ@@@@@@@@@@@¾Î°£I"­@J`%å7\êolÿÿÿÿà ¢­{´?ÿÊñÿÿÿÿÿýÌ_F߀`˜Âø$ ªâàÿäÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþú”ÿàú?ÿÿÿÿÿÿÿÿÿÿÿ¿¤ÿ¿¤ÿÿÿÀŸÙ@?eP>"X?ÿߣÿ÷ÿÿÿÿÿþzwÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿĦ4·22·12¹3/³¬ÇõRPh|t ×Më;«×ÿÿÿÿøCa{YíOÿñÿÿÿÿþür‘¨X$0Ü f€ÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿõ)ÿÁãôÿÿÿÿÿÿÿÿÿÿÿHÿÿHÿÿÿÿ?²0þþÉ`3|Eÿ¿Gÿïÿÿÿÿÿü† %Cÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿÿþ)Duesseldorf _gX y¥dsòà"6›¢q—¶?ÿÿÿÿð †ïö×¹¿ÿï ÿÿÿÿÿþÀæ¦\°0D€ìŒ7P°ÿò?äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ýJð4ýÿÿÿÿÿÿÿÿÿÿÿßÒ?ÿßÒ?ÿÿÿàOìªß¿²¨ßhŸÿïÑÿûÿÿÿÿÿÿ·  ÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠm’Ø\ÜÙ[ÙÀÖ^iÑ!h S)¦1òÿÿÿÿü!´}°Ú¯ÿùÅÿÿÿÿÿÉÿ…ÿÿüü/…‡ÿäÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ=¿üÿàú?ÿÿÿÿÿÿÿÿÿÿÿ¿¤ÿ¿¤ÿÿÿÀŸÙ@e¾"€ ÿÿߣÿ÷ÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿßÿÿÿê¦2´¸=4³–©±´5²º²4º=/³¬¾ƒÒJ¬˜¾ uÍy; áÿÿÿÿøCh ^mÿôâÿÿÿÿÿ,u6`"@  FÀÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿõ)ÿÀôÿÿÿÿÿÿÿÿÿÿÿHÿÿHÿÿÿÿ?²¨ þþÊA|EP%ÿÿ¿Gÿïÿÿÿÿÿÿÿÿÿÿÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿÿþ)èDresden-Klotzsche _gX u‰„ž—è0ü´™bw7¾?ÿÿÿÿð †É6«Hÿÿåÿÿÿÿÿý‘‚`À DDëÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿêSÿƒÇèÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿÿd°)ýý’Àêø‰`{ÿÿ~ÿßÿÿÿÿÿùWÿûôÿÿÿÿÿÿÿÿÿÿÿÿÿüSôœêÊäÄêäÎZ„ÂäîÊÒØÊä@@¾Î°Å‘Èé!°ŠHE9'„å”ÿÿÿÿà «m?ÿ×qÿÿÿÿÿýÜ Aï€ ¹ùòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊþƒ?ø~ÿÿÿÿÿÿÿÿÿÿÿïéÿïéÿÿÿð'öioß٠ψæßÿ÷èÿýÿÿÿÿÿÿÿÿÿÿÿÿ¿Gÿÿÿÿÿÿÿÿÿÿ÷ÿÿÿÅD‰¬­-Í-Ìì­Ä ìàk¬öt‘? M)Ò£NÎöÇÿÿÿÿþ×–Ö£sÿüWŸÿÿÿÿÿØÂ4¾ø Ž€ÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿüfÿå+ÿ€èÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿÿePýý•@‚øŠ Lÿÿ~ÿßÿÿÿÿÿøed‡ÿûôÿÿÿÿÿÿÿÿÿÿÿÿüTúŒäÂÜÖÌêäè^šÂÒÜ@@@@@@¾Î°¶4þ: P(6LêOtÿÿÿÿà ´-¿ÿÎÿÿÿÿÿýÜ<Çï€@¨Áä'_ÿ#þOÿÿÿÿÿÿÿÿÿÿÿÿÿÿøUÿÌ'ÿÑÿÿÿÿÿÿÿÿÿÿÿýý ÿýý ÿÿÿþþËà ûû/€ÉñÀgÿþýÿ¿ÿÿÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿþÿÿÿøªµ!½˜€€€€€€€€€€€€€€€€}œ `5†x’L‚a-˜—"LéÝŸÿÿÿÿÿÀ2ãÚ¶,ÿŒƒÿÿÿÿÿöCˆ:™rÀÐF¬þGüŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿ©Oþ£ÿÿÿÿÿÿÿÿÿÿÿûú@ÿûú@ÿÿÿü ý’À]÷öK£â%Sÿýú?ÿÿÿÿÿÿãs!Ì_ÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿñW›£«££; “¡j+C£+“#Ks:û8Àiϼ$„Aáà÷d²s±=Ñÿÿÿÿÿ€d7 µ¿½ÿÿË'ÿÿÿÿÿö!5‚C  ”3 €Üÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿêSÿƒWèÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿÿeð ýý—ÀVø‹à+ÿÿ~ÿßÿÿÿÿÿÿÿÿÿÿÿûôÿÿÿÿÿÿÿÿÿÿÿÿÿüUöœêÊäÜÄÊäÎ@@@@@@@@@@@¾Î°›½ <Ðo8/´îÏ|ÿÿÿÿà ’misÿÿÏ¡ÿÿÿÿÿü±Ð}F¡`@ Ãè%Öÿ#þOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿÔ§ÿÑÿÿÿÿÿÿÿÿÿÿÿýý ÿýý ÿÿÿþþÈÀ*ûû#çÿÀÿÿþýÿ¿ÿÿÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿÿÿÿÿø¬QMÑÉ…Õ‰¥¹œ€€€€€€€€€€€}œ `4õ{]-àê¨v]Éä¸ÿÿÿÿÿÀ2ÃZÃrÿ„çÿÿÿÿÿó?ø.ÿÿÀA/Ápÿò?äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ›ŸýJðýÿÿÿÿÿÿÿÿÿÿÿßÒ?ÿßÒ?ÿÿÿàOìn/¿± ŸÈÿïÑÿûÿÿÿÿÿÿ [ [ÿÿ~ÿÿÿÿÿÿÿÿÿÿïÿÿÿŠÕ]YÜØ\™ÈÙÀÖLâÉ#[&Ó‡åGýîÿÿÿÿü!±…¬wÿúq?ÿÿÿÿÿd@ ‡—0 €:ÀÿäÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþú”ÿàñú?ÿÿÿÿÿÿÿÿÿÿÿ¿¤ÿ¿¤ÿÿÿÀŸÙTe¾"€ÿߣÿ÷ÿÿÿÿÿþX0%ÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙ%²¶¸:2·³¬‘4ÂDÜP+,•Ès;Ó×ÿÿÿÿøCbS ÿóŠÿÿÿÿÿþûÿ;ÿø)ùÛ DàÿÈÿ“ÿÿÿÿÿÿÿÿÿÿþ ÿÿüÿõ)ÿÁãôÿÿÿÿÿÿÿÿÿÿÿHÿÿHÿÿÿÿ?²¾þÈ |EPÿÿ¿Gÿïÿÿÿÿÿü¦p5oÿýú?ÿÿÿÿÿÿÿÿÿÿÿÿÿþ7777dballe-7.7/extra/bufr/ed4-empty.bufr0000644000175000017500000000121712652630043014306 00000000000000BUFRY Ù  ÀÇPdNH€_Z;%–p”š[YHÛØÙ[ÝšXÙH˜ZKT^ž[™HX™\™XÈšXž\Û]ˆœ››ËU\˜[žHÜݘ]˜KS[Üۛ݀}0ÀÔTªHɶv—#™Þx§Ü JĘ @(Ri09HôµaíxN1 …9En8Ãëcƒ'&ÎUYD¬0²ÖÀ ŠÇ)B&yfyñ~…’»Ò"$¬ 8Jˆÿð$"ø$àa‹^µ¦l”crYJ‘( 0ä¨ÐB4`ð¢,æðEñª(@P\º €ê”Æ‹€`S'ÿàÿ€dÿåÿþ˜¿ø8 ÿà@¬ Bp2UýøÊ ÿôÿø7ÿãÿà€"€¥!Á@ýÿÁÁY@„àdª,3þ/ÿ€FÿÿáÿÀ@,þàð<Àÿ€@ð þàÿÿüÀÿÿÿøÿüÿðCüöÖ@ Ÿô –Wb,ªÄüþôÿÀ`1Bøÿ€ÿàb×­@ ÿðÐÿü2Ž\È9¦È€û$nU U@ SÅQ‘@|öþÿ€é€Àÿð?ÿÀ~€<üÿÿÀÿð?ÿÿþÿøÿà?@þÿÿüÿð?ÿÀÿÿÿÀÿð?7777dballe-7.7/extra/bufr/obs0-1.22.bufr0000644000175000017500000000033412652630043013720 00000000000000BUFRÜb€  4}Ky€BŽ^ƒP60150 Üy„yƒ F€Ç  –A1 A1!nxK/©o0è5p°L¹Ñž((E¦YOñŒ,€ÀAŸß"@J@f ‰Ÿÿÿüoÿð hÑ£F4hÒåJ›>4jcR«5XÕjU«V4hÑ£F4hÑ£F4`7777dballe-7.7/extra/bufr/temp-huge.bufr0000644000175000017500000023663412652630043014406 00000000000000BUFR=œcdÿÜ 8€É4QRC_`a=…<=` ‚€( ‡“î2‹'†Æ¡R5ÿÿÿÿ€û›+t(œÐŽ*kˆ•=»ŽËt Pˆ‘*k•=#Žssà  ˆÑ*k•=#Žssà ‚*j¨•<ËŽ3sؤ|!Ñ*i¨•(•(óƒq˜È6ŒŠ‘*=ˆ•(³q˜Ä7†Q*=•(€»q`ÀP8€*;È•';€[q ÀP9z’‘*9è•&‹ûpø¼:t•Q*8ˆ•&;›pð¸Ð;m˜‘*7è•%ÛCq¸Ð<f›‘*7•%#~ëq´=`žQ*5(•$K~›q°P>Z Ñ*3(•#«~Sq°?T£‘*1È•#K~ pø°@N¦Q*0¨•"ë}Ëpè¬PAH©*.è•"“}‹pجÐBA¬Q*-•"K}#pذC9¯‘*,•!û|»p¸°D2²Ñ*+ˆ•!k|Spx°ÐE+µÑ**È• »{ópP´PF$¹*)(• C{“p@´G¼*(• {3p@´ÐH¿Q*'È•£zËp¸ÐI ÁÑ*'h•ózkoиÐIÂ*'h•ózcoȸÐJ ÄÑ*&(•[z o°¸ÐKÇ‘*$¨•#y³oдÐLýÊÑ*#¨•ûyko¸´MöÍÑ*#•kyKoP´NðБ*!è•£xëo8°POëÓ* •3x‹oX°PåÕ‘*¨• xKo8°ÐQߨ‘*è•Ëwão@°ÐRÚÛ*(•#w{o0°SÕÜÑ*ˆ•swSnÀ°PTÑÞÑ*¨• wÓlè°PUÍàÑ*¨•ËxcjȰVÈâÑ*È•SxKj´WÃå*ˆ•«x3ix´ÐX¾çQ*(•;x#i@¸ÐY¹éÑ*(•ãwëi¸ÐZ´ìQ*(•Sw³i¼[¯î‘*è•»w‹iP¼\ªñ*¨•KwCiHÀ]¤ó‘*È•Óvûi ÄP]€¡õ*È•3vÓi(ÄP^ŸõÑ*È•3v»i0ÄP_šø* h•›v‹ipÈ`•ú‘* h•+vSi°ÌaüÑ* h•³vCjÌÐb‹ÿ* è•vj(Ðc…‚Ñ*h•“uãj0ÔdÑ*ˆ•óu£jÔPey‘*•;uSiÐØfs‚ Q*•›tói°ÜÐgn Ñ*è•t›i Ühi*è•stSi€àPidQ*È•“ti@äj^‚Ñ*h• ÛsãiäkY‚Q*h• ks«ièÐlUQ)ÿh• ÛskhøèmQQ)þH• shÐìnL‘)üÈ• CrÛh¸ðPoG)û¨• ³r“h€ðPpB‚!)û(• rchPôPq?"Ñ)úh• #r;h øPr;$‘)ù(•3rhüPs7‚&Q)ø(•{qÛgðüt4‚'Ñ)÷h•ëqÃgÑu1)Q)öè•Cq‹g©v-‚+)ö(•‹qSgÐw*,‘)ôè•Ãq+g‰x&‚.)óè•qgñy#‚/Ñ)óH•[pÛhQ Pz 1Q)òè•«pƒh1 P{‚3)òH•ûpKgÙ |4Ñ)ñH•Cp#h}6‘)ðh•ƒoûhÙÐ~8)ïÈ”ÿÃoãiaЂ9‘)ï(”ÿo³i¡€ ‚;‘)þkoƒj P=Q)íè”ý»oSj‚‚>Ñ)í”ý o#jÁ Ѓ@‘)ì(”üCo k „üBQ)먔û£nëk P…ø‚D)ë”ûnÓjñ †ô‚EÑ)êh”ú{n«j¹ Їð‚GÑ)éÈ”ùËnƒjaPˆì‚IÑ)é”ù#ncj)‰è‚KÑ)訔ø£nciñЊåMQ)çè”ø3n#i¹P‹áOQ)ç”÷›mÃi©ŒÜ‚QQ)æH”öûm“i©ÐׂSÑ)åÈ”öSm{iqŽÒV‘)åH”õ»mKiPÌ‚Y)äÈ”õkmShIPÇ‚[‘)äH”õ;m[gÁ ‘Â]Q)ãH”ôÃm+gÐ’À_)â(”ô lëgQГ¼‚`Ñ)ᨔóKlãg!”¹b‘)ሔò«lËf‘P•µd‘)áh”ò;l£fI P–±fQ)á”ñÓl{f)(—­‚h)àh”ñClKf ,И©jQ)ßÈ”ð£leñ4P™£‚m)߈”ðkãeÙ<š‚o‘)ßh”ï‹kÛeQD š šq‘)ߨ”îëkãdÑL P›˜‚r)ߨ”îëkëd™L Pœ“‚tÑ)à”îckãd!T ÐŽwQ)à(”î#kûd\ Pžˆ‚yÑ)ßH”íãkÓd)d Пƒ‚|‘)Þh”íSkƒdl P }‚Q)Þ¨”ìƒkScñx ¡x‚)à”ëãk{dQ€ ¢s„Q)àè”ëÃkƒd¹ˆ P£o†Q)àˆ”ëÓk[e” ¤l‡Ñ)ßÈ”ëÃk;eœ Ð¥h‚‰‘)ßÈ”ëskdé¨ ¦d‹‘)àˆ”êójãd±´ P§`‚‘)áH”ê[j³d™À P¨]Q)áÈ”éëj“d¹Ì ©Y‘)ᨔé£jcdÉÜ ªU“)áh”ésjCdñìЫQ•)ᨔé+j+eЬM‚–Ñ)âh”èÓj eЭJ˜Q)ã”èƒje2(ЮF‚š)㨔èCj eš<ЯCœ)äH”è#ióeúPа?ž)åH”è#iãf2d ±;ŸÑ)æH”èj f¢t ²6¢Q)ç(”çãj«gjˆ P³0‚¥)è”çÃk[gò” P´+‚§‘)é”çók“gº¤ µ&‚ªQ)ê(”èksgJ° ¶!‚¬Ñ)ë”çók+fê¸ ·‚¯)먔çÃjëfºÀ ¸‚±‘)ìh”çÓj«fšÈ ¹³Ñ)íÈ”çëjkfjÌ º¶Q)îè”çÓjCf:Ð » ‚¸‘)ïH”çÃj#f2Ô ¼º‘)ïÈ”çóiëf:Ø P½‚¼)ðè”è;iÛfBÜ P¾ÿ½Ñ)òH”èCiÃf"Ü P¿ü¿Q)ó(”èi«eúà ÀùÁ)óH”çûiƒfà Áõ‚‘)ó¨”çûi[fä ÂòÄQ)ôˆ”èi#eêä ÃïÅÑ)õ¨”è;ie²ä ÄìÇQ)öˆ”èKhûe’ä ÅéÈÑ)÷(”è3hÃezä Æå‚Ê‘)÷ˆ”è#h‹ejä PÇâÌQ)øh”è3h[eRä PÈßÎ)ùˆ”è[heä PÉÜÏQ)ú¨”èƒgódòä ÊÙÑ)ûh”èsgÓdâà ËÕ‚Ò‘)ü(”è[g«dÊà ÌÒ‚ÔQ)üè”è[g›dºÜ ÐÍÏÖ)ýÈ”ècg“dšÜ ÎË‚×Ñ)þ¨”èsgsdzÜ ÏÈ‚ÙQ)ÿˆ”ècgdšØ PÐÅ‚ÚÑ*h”èSfÓdšØ PÑ‚ܑ*H”è[fËdJÔ Ò¿‚Þ*”ècfÓcÊÔ ÐÓ¼‚ß‘*”èkfãcrÐ Ô¹áQ*”èsg cÐ Õµ‚âÑ*h”èkg#bšÐ PÖ²‚ä‘*¨”ècgbZÌ ×¯‚æ*h”ècfóbRÌ Ø¬‚ç‘*H”è{fÃb2Ì ÐÙ©éQ* H”èƒf“bÈ Ú¦ë* H”èkf[b2È Û¢‚ì‘* ˆ”èSf+bÈ PÜ î* ”èKf;a²Ä PÜŸ‚îQ* ”èKfCa¢Ä PÝœð*(”èKfSaRÄ Þ™ñ‘*(”è[fKa"Ä ß–ó*è”èSfa2À Ðà“‚ô‘*(”èCeÓaZÀ Ðá‚õÑ*¨”è;e»ajÀ ÐâŽ÷Q*”èCeËabÀ ã‹øÑ*”è;e“`òÀ äˆúQ*è”è+es`jÄ Ðå…ûÑ*”è e[`"È Ðæ‚ýQ*H”çãeS_¢Ì çþÑ*È”ç³e[^ÚÐ Pè|Q*”çËeS]êÔ éy*(”çëe+\ÚÜ Ðêu*H”èe3[²ä ëqƒÑ*H”è eëVÂð Pìn‘*(”ègKKø ík Q* (”èi :{ Ðîh Ñ*!”èjƒ [ ïe Q*!È”è[k3C Pðb*"h”è£k{( Pñ_‘*#”èÃkƒ Ë4 ò[ƒQ*#È”èãkc Û< óX*$ˆ”ékK{H ôUƒ‘*%h”éKksëP PõRƒ*&h”é{kšüÃT PöOƒ‘*'(”é«kj÷{\ P÷LQ*'È”éÛk"õû` øIÑ*(”êköCh ùF‘*(¨”ê[kõ“l ÐúBƒQ*)È”ê£júò³p Ðû?ƒ **¨”êójªñSt ü<!Ñ*+ˆ”ëCj²ðót ý9#Q*,H”ë“jºñx þ6%*,È”ëËj¢óÛ| Pÿ3&‘*-h”ìj‚÷ƒ| Q/ƒ(Q*.(”ìKjzøã€ Q,ƒ**/”ì«j‚ù+„ ‘)+‘*/è”ìûj:ù„ ‘&-Q*0h”í3jøËˆ ‘#/*1”í{jj÷[ˆ Ñ 0‘*1è”íÃjªñ[Œ у2Q*2È”îjÚçsŒ 4*3È”îkjâß«Œ 5Ñ*4H”î«jÂÜ£Œ Q 7Q*4¨”îój²Û“ ‘ 9*5H”ïKjÂÚÛ ‘  :‘*6(”ï«jÂÚ Ñ  ƒ*7¨”ðkjšÚ+Œ ƒ?Ñ*8h”ðËjŠÛcŒ QA‘*9(”ñ#jŠÜóŒ QýC*:”ñƒj‚ÞƒŒ ‘ùƒDÑ*;(”ñãjjàKˆ ‘öƒF‘*<(”òKjR⣈ ‘óƒH*=”ò£j*äÛ„ ‘ðƒIÑ*=¨”òûjåÄ ‘íƒK‘*>(”ó[iò囄 ‘êMQ*?(”ó»iÚå€ ‘çNÑ*@(”ô iÂä;€ QäP‘*AH”ôkiªãó| QàƒRQ*B(”ôËizä| ÝTQ*C”õiJäC| ÚV*CÈ”õci"ä3x Ñ×W‘*D¨”õ«hòäx ÑÓƒYQ*E¨”õûhÂäx ‘Ѓ[*Fˆ”öKh’ããt ‘̓\Ñ*Gh”ö›hZã»t Q ʃ^Q*H(”öãh2ã£t Q!ǃ_Ñ*Hè”÷+h ã»p "ăa‘*I¨”÷cgêãëp #Áƒc*Jh”÷“gºäp $¾ƒdÑ*K(”÷Ûg’ä›p %»ƒfQ*L”ø;gbäûl &¸ƒh*LÈ”ø“g2å#l Q'µiÑ*M¨”øÓgå‹l Q(±ƒk‘*Nh”ù fâæ{l ‘)®ƒm‘*Oh”ùKfÊçãh ‘*«oQ*Ph”ù“fªèëh Ñ+¨q*QH”ùãfŠé[h Ñ,¥r‘*R(”ú3fjéÃh -¡ƒtQ*S”ú{fRêËh .žƒv*T(”ú»f"êãl /›ƒwÑ*UH”ûeúé«l Q0˜ƒyQ*V(”û[eÒè{l Q1•ƒ{*W”û»eªç‹p Q2’ƒ|‘*WÈ”üezæóp Q3ƒ~Q*X¨”üKeZæ“t Q4ŒƒÑ*YÈ”ü‹eBæ3t Q5ŠQ*Z¨”üëe*åÃx Q6†ƒƒ*[ˆ”ýSe åCx 7ƒƒ„Ñ*\H”ý»dòäã| 8€ƒ†‘*](”þ dêäƒ| Ñ9}ƒˆ*^”þKdêã[| Ñ:zƒ‰Ñ*_”þ›dêá{€ ‘;wƒ‹‘*_è”þódâàû€ Q<tƒ*`¨”ÿSdÊàÓ€ =qƒŽÑ*ah”ÿ»d²à{„ Ñ>nƒQ*b•d¢à[„ ‘?l‘Ñ*b¨•3dšàs„ Q@hƒ“‘*c(•kdšàSˆ Aeƒ•Q*cÈ•³d¢ßÛˆ ÑBbƒ—*dh•d²àƒˆ ‘C_˜Ñ*dè•CdÊå3ˆ ‘D\ƒš‘*e¨•sdÊïŒ ‘EYœ*fh•³d²ûcŒ QFVž*g(•dƒŒ QGSŸ‘*gÈ•[dK‹ˆ QHP¡*hH•£dˆ QIM¢Ñ*h¨•ëcë#ˆ QJJ¤‘*i(•3c»k„ QKG¦Q*j•sc“K€ ‘LD§Ñ*jè•»c‹| ‘MA©‘*k¨•cc£x ‘N>«Q*l•Sc;‹t ‘O;¬Ñ*l¨•£c+»t ‘P8ƒ®Q*mH•Óccp ‘Q5ƒ°*nH•óc l ‘R2±Ñ*oh•bû{h ‘S/ƒ³Q*ph•cbã;d ‘T,ƒ´Ñ*q•³bÃkd ‘U)ƒ¶‘*qˆ•ûb³ ` ‘V&ƒ¸Q*r(•#b£ ` QW$¹Ñ*rè•Kb{c` QX!»‘*sÈ•ƒbKk` QY½*t¨•Ëb#k` QZƒ¾‘*uh•aû[` Q[À*v•Kaãó` Q\Á‘*vè•sa³K` ‘]ÃQ*w¨•£a{»` ‘^Å*xH•ÛaCó` ‘_ ÆÑ*xè• aÃ` Ñ` ƒÈ‘*yˆ•;`ó` ÑaÊQ*zH•s`Ë` bËÑ*{H•³`«d cÍ‘*|H•ó`‹ »d d þÏ*|è• ;`{ kd Qe ûƒÐ‘*}¨• ƒ`Sƒd Qf ùÒ*~ˆ• Ã`;ëh ‘g öÓÑ*h• `+ëh ‘h óÕQ*€h• S`«l ‘i ð×*(• £_ëël ‘j íØÑ*è• Û_³ûp ‘k êÚ‘*‚ˆ• _‹#t Ñl çƒÜ*ƒ(• C_kt Ñm äƒÝ‘*„(• ‹_Cûx Ñn áƒßQ*…(• Û_û| Ño Þƒá*†• #^〠Ñp Üâ‘*†È• s^Ã#„ Ñq ÙäQ*‡H• ³^›Œ r ÖåÑ*‡è• ó^sS s ÓƒçQ*ˆ¨• ;^CC” t ЃèÑ*‰ˆ• £^Ó˜ u ̓êÑ*ŠH• ]û{œ v ʃìQ*Šè•{]Óœ w Èî*‹ˆ•ë]³  x Åï‘*Œ•K]‹㤠y ÂñQ*ŒÈ•³]ƒ ¤ z ¿òÑ*H•]k£¤ Ñ{ ¼ô‘*È•c]S+¤ Ñ| ¹ƒöQ*Žh•³]#ä Ñ} ·÷Ñ*•\û$³¤ ‘~ ´ùQ*¨•s\Û'k¤ ‘ ±û*h•Ë\£+à Q€ ®ƒü‘*è• \ƒ3Ë  Q ¬þ*‘h•S\{7à  ¬þ*‘h•S\s7Û  ‚ ©ƒÿ‘*’•£\k7#œ ƒ §*’È•ë\C6Cœ „ ¤‘*“h•C\#4 œ … ¡Q*“è•“\ 0£œ † ž„Ñ*”h•ë[ë/#œ ‡ œQ*••C[Ã.#œ ш ™„Ñ*•¨•ƒ[«,+œ щ — *–h•Ë[›*[œ ÑŠ ”„ ‘*—•[ƒ++  Ñ‹ ’ *—¨•[[c-;  ÑŒ „Q*˜H•«[C-#¤ Ñ Ñ*˜è•[#,»¤ ÑŽ Š„Q*™h•[Zû,ˤ Ñ ‡„*š•»Zã-+¨ Ñ …‘*š¨•ZË.˨ ‘‘ ‚„*›H•KZ«.‹¨ ‘’ €‘*›¨•“Z“-“¬ ‘“ }„*œ(•óZk-ƒ¬ Q” z„‘*œ¨•KZS*c¬ • x*(•›ZK$3¬ – u„‘*¨•ÛZcû¬ Ñ— r„Q*ž•Zc ¬ ‘˜ p„ ‘*ž¨•kZKK° Q™ n"*Ÿ(•«Z3";° Qš k#‘*Ÿˆ•ëZ3û° › h„%* (•+Z#Ó°Ñœ f&Ñ* ¨•kZS´‘ c(Q*¡•£Yãc´Qž `„**¡ˆ•ÛYÓË´QŸ ]„+‘*¡è•YÓ û¸  [-Q*¢h•cYËK¸Ñ¡ X.Ñ*¢¨•³YÃ+¼‘¢ U„0Q*¢è•ûYÂùÛ¼‘£ S1Ñ*£(•3YªöûÀQ¤ P„3Q*£(•kYŠ÷CÀQ¥ M„5*£h•‹Yjý3À¦ K„6Q*¤•ÃYKÛÀ§ I7Ñ*¤¨•Y3¼¨ F9‘*¤è•CY“¼Ñ© C„;*¥•{Xóƒ¸Ѫ A<‘*¤è•«Xã;¸Ñ« >„=Ñ*¥H•ÓX³³´Ѭ <?Q*¥è•X“›°Ñ­ 9„A*¦h•KXƒë¬Ñ® 6„B‘*¦È•“X[¨ѯ 4DQ*§•ËX;K¨Ѱ 1EÑ*§(•ÛX#»¤ѱ .„G‘*§h•ûX C¤Ѳ +„I*¨•#WÛ “ ѳ )JÑ*¨ˆ•SW³3 ´ &LQ*¨è•“W³[ µ #„N*©(•ÓWƒ;œ¶ !O‘*©h• W{Kœ· Q*©è• CW[ Q¸ R‘*ªh• kW;Ë Q¹ „T*ª¨• “Wû ‘º „U‘*ªè• ÃVóC ‘» WQ*«H• ûVóC¤Ѽ Y*«è•!;Vó¤ѽ „Z‘*¬H•!sV볨¾ „\‘*¬¨•!³V㓨¿ „^*­(•!ûVóƒ¬QÀ _Ñ*­ˆ•";WˬQÁ aQ*®•"{W›°‘ „c*®ˆ•"ÃVóC°‘à ý„d‘*¯•# VÛ³°‘Ä ûfQ*¯h•#SVà °‘Å øgÑ*¯¨•#“V£3´‘Æ õ„i‘*¯è•#ËV{[´‘Ç ók*°h•$VK‹´‘È ð„l‘*±•$SV3«´‘É í„nQ*±¨•$£V#£´ÑÊ ëp*²(•$ëUûë°ÑË èq‘*²(•%3UãC°ÑÌ å„sQ*²h•%kUÓë´ÑÍ â„u*²è•%›U³3´ÑÎ àv‘*³¨•%ËU‹û´ÑÏ Ý„xQ*´(•&Usk¸ÑÐ Ú„yÑ*´¨•&cUSs¸ÑÑ Ø{Q*µ•&«U#3¼ÑÒ Õ„}*µh•&ûUûÀÑÓ Ò„~Ñ*µè•'CTãÄÑÔ Ð€Q*¶H•'ƒTÃÈÑÕ Í‚*¶È•'ÛT£‹ÌÑÖ Ê„ƒÑ*·H•(+T“+Ð‘× Ç„…‘*·H•({T{£Ø‘Ø Å‡*·H•(»Tk Ü‘٠„ˆ‘*·h•(ûT[³à‘Ú ÀŠ*·è•);TKÛä‘Û ½„‹Ñ*¸h•)ƒT;;èQÜ »Q*¸È•)ãTûìQÝ ¸*¸È•*;SóëðQÞ µ„‘*¸È•*ƒSÛëðQß ³’*¹•*ËSÃÃôQà °„“‘*¹H•+ S£{øQá ®•Q*¹ˆ•+cS‹ûøQâ «–Ñ*¹¨•+»S“;øQã ¨„˜Q*¹È•+óS«£üQä ¦š*¹è•,+S›‹üQå £„›‘*ºH•,ƒS{“üQæ ¡Q*ºh•,ãS[{üQç žŸ*º¨•-CS3|‘è ›„ ‘*º¨•-›S l‘é ™¢*º¨•-ËRëL‘ê –„£‘*ºè•-ûRÓl‘ë ”„¥*»h•.KR³œ‘ì ‘„¦‘*»¨•.“R‹¤Ñí ¨Q*»è•.ÛRcœÑî Œ„©Ñ*»è•/3R#”Ñï ‰„«‘*»È•/“Që¤ ð ‡­Q*¼•0QÛü ñ „„®Ñ*¼H•0SQ›“ü ò „°‘*¼h•0“QsÃø ó ²Q*¼¨•0ÛQKø Qô |„³Ñ*¼è•13Q+kô Qõ zµQ*½(•1“Q {ð Qö w·*½ˆ•1óPëCð ‘÷ t„¸‘*½è•2CPËûì ‘ø rºQ*¾H•2ƒP«Óè ‘ù o„»Ñ*¾ˆ•2ËPƒ“è Ñú m½Q*¾È•3#Pk+ä Ñû j„¿*¿H•3‹PC»ä Ñü hÀ‘*¿È•3óP sä ý e„Â*À•4COëà þ cÃÑ*À•4‹OÓ«à ÿ `Å‘*ÀH•4ÓO«#à  ]„Ç*ÀÈ•5;Ok[à  [ÈÑ*ÁH•5£O;cÜ R X„ÊQ*Áˆ•6O+ƒÜ R VËÑ*ÁÈ•6[O“Ü R SÍ‘*Áè•6³NÛ³Ü R P„ÏQ*ÂH•6ûN³»Ø R NÑ*ÂÈ•7CN‹«Ø  KÒ‘*ÃH•7“Nc³Ø  H„ÔQ*ÃÈ•7óNC»Ø  FÖ*Ä•8CN#³Ø  C„ב*Äh•8“N ³Ø  AÙ*ÄÈ•8ëMãËØ Ò >ÚÑ*ÅH•9KM»ëØ Ò ;„Ü‘*Ũ•9£M‹ÓØ Ò 9Þ*Åè•:Mk»Ô Ò 7ß‘*Æ(•:SMK“Ô ’ 4„á*ƨ•:ƒMcÔ Ò 2â‘*Ç(•:«Lû3Ô Ò /äQ*Lj•:óLã3Ð Ò -åÑ*Ǩ•;cL»KÐ  *„çQ*ÇÈ•;ËL“[Ì R (èÑ*È(•< L‹ãÌ ’ %„êQ*ÈÈ•<;Lk+È Ò #ìQ*É(•<‹LSsÈ R î*Ɉ•<ûL;ãÄ ’ „ïÑ*Ê(•=[LËÄ  „ñ‘*ÊÈ•=³LKËÄ R ó*ˈ•>Lc Ä ’ „ôÑ*ÌH•>‹L£Ä Ò öQ*Í(•?KÃËÄ Ò ÷‘*Íè•?»KË‹À  „ù*Îh•@;Kë{À  úÑ*ÎÈ•@›Kë³À ! ü*Ï(•@óKëÛÀ " „ý‘*ÏÈ•ASKã‹À Ò# ÿ*Ј•A«KÛÀ Ò$ ‘*Ðè•B KÓÓ¼ ’% …Q*Ñ(•BcK«³¼ ’& þ…‘*ÑÈ•B³Ks{¼ ’' ü*Ò¨•CKS£¼ R( ú‘*Óˆ•C›Kc³¸ R) ÷…*ÔH•D K;£¸ R* õ ‘*Ôˆ•DcK«¸ R+ ò… *Ôè•D›K ƒ´ ’, ð… ‘*Õˆ•DóJË‹´ ’- î… Ñ*Ö(•E{J“«´ ’. ì…*Öˆ•FJ£Û´ Ò/ ê…Q*וFKJ‹«´ Ò0 è…Ñ*×È•FƒJS´ 1 æ…*ب•FÛJ[“´ 2 ä‘*Ùh•GcJK£° R3 â*Ú•GûJC° R4 ß…‘*Ú¨•HkIû³° ’5 Ý…*Û(•HÃIË£° ’6 Û‘*Û¨•IIÛ+´ ’7 Ø…*ÜH•IkI»£´ Ò8 Ö…Q*Ý(•IãIK‹´ Ò9 Ô…Ñ*Þ•J{IS´ Ò: Ò Q*Þè•JëI3³¸ ’; Ï…!Ñ*ߨ•K;I û¸ ’< Í#‘*àH•K‹Hë ³¸ ’= Ë$Ñ*ਕLHã û¼ ’> È…&Q*á(•LƒH« C¼ R? Æ…'Ñ*ᨕLëH[ kÀ R@ Ä)‘*∕MKH# ëÀ RA Á…+*ã•M£Gû £Ä RB ¿…,‘*㈕NGû [Ä RC ½.*ä•NƒGÛCÄ RD º…/‘*䈕OG‹{È RE ¸…1*å(•OƒG‹ »È ’E ¸1Q*å(•OƒGƒ sÈ ’F ¶…2Q*åÈ•OëGc sÌ ’G ´3Ñ*æH•PKG3 CÌ ’H ±…5Q*樕P«G ãÌ ÒI ¯…6Ñ*ç(•Q#FÛÛÌ ÒJ ­8‘*çè•Q›F»ËÐK «9Ñ*舕RF‹ËÐL ¨…;Q*é•R‹FcÓÔM ¦…<Ñ*éh•RóF;cÔN ¤>Q*éè•SkF+ÔRO ¡…@*êh•TEë3ØRP ŸA‘*ë•T‹EÓØRQ C*먕UE³KÜR š…DÑ*ìH•UsE«ÓÜS ˜FQ*ìÈ•UÛE›CàT •…H*íH•VSE{ƒäU “I‘*íÈ•VËEKKä ÒV …KQ*î(•W[E3ä ÒW Ž…LÑ*WÛDóÓè ’X ŒNQ*îÈ•XCDÃ[è ’Y ‰…P*ï•X«D£[è ’Z ‡Q‘*ïh•YD{Ãè R[ „…S*凞YƒDK;è R\ ‚TÑ*ð(•Z D+Ãè R] …V‘*ð¨•Z“D#è R^ }XQ*ñ•[ CÛ[è R_ {YÑ*ñH•[kC£{ä R` y[*ñÈ•[ãCƒ›ä Ra w\Q*ò(•\[Cc ä Rb t…]Ñ*òˆ•\»C;Ãä ’c r…_Q*òè•]#C ;à ’d p`Ñ*óh•]£Bë«à ’e nbQ*ô•^BËcà Òf k…cÑ*ô¨•^‹B«;à Òg ie‘*õ•^ûBƒóà Òh gg*õˆ•_kB[Ëài d…h‘*ö•_ëB3»àj b…iÑ*öh•`{B‹àk `…kQ*öÈ•aAã[àl ^lÑ*÷h•asA»ûàRm \nQ*÷è•aãA“ÃàRn Y…p*øh•bSA[ãàRo WqÑ*ù•bÃA+óàRp T…sQ*ù¨•cKAóàRq R…tÑ*ú•cÓ@ãÃàRr PvQ*úh•d[@»‹àRs NwÑ*û•dÛ@‹[àRt K…yQ*û¨•eS@[3àRu I…zÑ*üH•eÓ@3#ÜRv G|‘*ü¨•f[@ Üw D…~*üÈ•fã?ÓóÜx B…‘*ý(•gC?«ËÜy @*ýÈ•g›?{›Üz >‚‘*þH•h?S£Ü{ <„*þÈ•h‹?#ûØ| :…‘*ÿh•hó?CØ} 7…†Ñ+H•ik>Û3Ø~ 5…ˆQ+¨•ië>«3ÔR 3‰Ñ+(•j{>{;ÔR€ 1‹Q+¨•jû>KÐR /ŒÑ+•k{>óÐ’‚ -Ž+(•kë=ëãÌ’ƒ *…‘+¨•lK=ÃóÌÒ„ (…‘+¨•l»=££ÈÒ… &…’‘+È•m;=k#ÈÒ† $”Q+h•m«=3Ûȇ !…•Ñ+è•n=  Ȉ …—Q+H•n“<ëSÄR‰ …˜Ñ+•o#<ËCÄRŠ šQ+è•oË<››ÄR‹ ›Ñ+¨•pc<{›ÄRŒ + H•pÃÑ+c¨•·+2:Ö›ÄRñ 0@Q+dˆ•·ó2Ö3ÄRò .AÑ+e¨•¸«1òÕûÄRó ,CQ+fÈ•¹[1ºÖÄRô *E+g蕺#1‚ÖCÀRõ '†F‘+i•ºó1RÖ³Àö %†HQ+j•»³1*ÖËÀ÷ #J+j蕼S1Ö»Àø !K‘+k蕼ó0ÒÖ£Àù MQ+l蕽³0¢Ö“Àú †NÑ+n•¾‹0jÖ{Àû †PQ+nè•¿[0:Öc¼Òü R+oè•À0 Ö[¼Òý SÑ+q•À»/ÚÖK¼Òþ †UQ+rH•Ác/²Ö¼Òÿ †W+sH•Â/zÕã¼Ó †X‘+tH•ÂÛ/BÕüÓ ZQ+uH•Ó/Õ«¼“ [Ñ+vH•Ä;.òÕ{¼“ ]‘+wh•Äã.ÂÕ{¼“ †_+xˆ•Å‹.’Õƒ¼“ †`‘+y¨•ÆC.bÕc¼“ †bQ+zè•Æû.*Õ+¼“ d+|(•dz-òÕ¼“ ý†eÑ+|è•È[-²ÔûÀ“ û†g‘+}¨•É-‚Ô³À“ ùi+~ˆ•ÉÃ-JÔƒÀ“ ÷jÑ+¨•Ê‹-"ÔƒÀÓ ô†l‘+€È•ËC-Ô£ÄÓ ò†nQ+È•Ëó,ÒÔ›ÄÓ ðp+‚¨•Ì›,ŠÔ‹Ä í†qÑ+ƒh•ÍS,jÔ“Ä ë†sQ+„h•Î,2ÔsÈS é†u+…È•ÎÛ+êÔ+ÈS çv‘+‡(•Ï£+ºÓëÌS åxQ+‡è•Ðk+ªÓËÌ“ ãyÑ+ˆh•Ñ3+šÓ£Ð“ à†{Q+‰H•Ò+ZÓ£ÐÓ Þ†}+Šh•Ò»+*ÓÃÔÓ Ý~Q+‹ˆ•Ós+ Ó«Ô Ú†€+Œh•Ô;*ÒÓCØS ؆‘+•Õ*²ÒƒÜS Ö†ƒ+è•Õû*ºÑƒà“ Ô†„‘+ŽÈ•ÖÛ*zгàÓ Ò†Q+ȕכ*rÏûä Ј+È•ØK*zÎ+äS Ή‘+‘h•Ù+*‚Ìè“ ˆ‹Q+‘È•Ú#*JÊKè Ɇ+’¨•Û*zÈ£ìS! Ç†Ž‘+“¨•Ü *ÊÆ3ì“" Å+”ˆ•Üã*ŠÄCìÓ"  Ä‘+•H•ÝÓ*zóðS# ÑÑ+•H•ÝÓ*rÃ;ðS$ Á“‘+•È•Þã*r“ð“% ¾†•+–H•ßë*BÁóðÓ& ¼†–Ñ+—(•àã*"Á[ð' º†˜Q+˜(•áÛ*ZÀóðS( ¸š+˜È•âã*¢Ácð“) ¶›Ñ+™ˆ•ãÛ*ÂÂËðÓ* ´Q+šH•äË*šÃÃðÓ+ ²žÑ+›(•åË*JÄð, ° Q+›è•æÛ*JÄð- ®¡Ñ+œÈ•çã*bÃÓðS. ¬£Q+È•èÛ**Ã;ðS/ ª¤Ñ+žˆ•éÛ*ÂëðS0 ¨¦‘+ŸH•êã)êÂÛð“1 ¦¨+ (•ëó)ÒÂÛð“2 ¤©‘+ è•í )ªÂ«ì“3 ¢«+¡È•î)ŠÂƒì“4  ¬Ñ+¢ˆ•ï)rÂSìÓ5 †®‘+£h•ð)BÂ;ìÓ6 ›†°Q+¤(•ñ#)ÂìÓ7 ™±Ñ+¥(•ò3(âÁëèÓ8 —³‘+¦•ó;(ÊÁÛèÓ9 •µQ+¦è•ô#(¢Á«èÓ: ’†¶Ñ+§È•õ#(zÁcäÓ; †¸‘+¨È•ö#(bÁäÓ< ކº+©¨•÷3(ZÀ£à= Œ†»Ñ+ª¨•øC(BÀ à> І½Q+«È•ùS(*¿sà? ˆ†¾Ñ+¬È•ú['ú¿Ü@ ††À‘+®•ûS'ê¾ÃÜA „ÂQ+¯(•üK'â¾kÜÓB ‚ÃÑ+°H•ýK'²¾ØÓC †Å‘+±(•þ['’½³ØÓD }†ÇQ+²H•ÿ['‚½KØÓE {†É+³ˆ–S'j¼ÃÔÓF yÊÑ+´¨–S'B¼SÔÓG wÌQ+µè–C'¼#ÔÓH uÍÑ+·–#&ò¼ÔÓI s†ÏQ+¸(–&Ê»óÔÓJ qÐÑ+¹H–&¢»óÔ“K oÒ‘+ºˆ–#&z¼Ð“L mÔ+»¨–3&R¼3ГM kÕÑ+¼È–C&"¼CГN i×Q+½È– +%ê¼;ÐÓO gØÑ+¾¨– ó%º¼ÐÓP eÚQ+¿è– Ë%¢¼ ÐÓQ cÛÑ+ÁH– ã%м#ÐÓR aÝ‘+ˆ– %Z¼+ÐÓS _ß+è–%:¼;ÐÓT ]†à‘+ÄÈ–%¼;ÐÓU [†â+Åè–ó$ú¼ÌÓV YãÑ+Ç(–Ó$Ê»ûÌÓW WåQ+Ȩ–Ë$¢¼ ÌX Uç+Éè–Û$м3ÌY SèÑ+Êè–Û$R¼;ÌZ QêQ+Ëè–Ã$¼#Ì[ OëÑ+ÌÈ–³$¼ Ì\ MíQ+ÎH–«#Ê»ãÌ] KîÑ+ÏÈ–³#š»ËÌ^ Ið‘+ÑH–«#Š»³ÌS_ Gò+Òh–³#Z»“ÌS` Eó‘+Óh–³#"»“ÌSa CõQ+Ô¨–«#»‹ÌSb AöÑ+Ö–£"Ò»CÌSc ?ø‘+×h–›"¢»ÌSd =úQ+ب–›"zºûÌSe :†ûÑ+ÙÈ–£"B»ÌSf 8†ý‘+Û– £"»3Ìg 6†ÿ+Ü(–!›!ê»KÌh 4‡Ñ+Ýh–"‹!º»KÌi 2‡Q+Þ¨–#{!Š»#Ìj 1Ñ+ߨ–$s!b»Ìk .‡Q+àˆ–%s!*» Ìl ,‡+áè–&s ú» Ìm *‡‘+ãH–'s âºûÌn (‡ Q+äÈ–({ ²ºãÌo &‡ Ñ+åè–)s ŠºËÌp % Q+ç–*S bº³Ìq #Ñ+èh–+; Bº‹ÌSr !Q+鈖,C *º{ÌSs ‡Ñ+ꈖ-S º»ÌSt ‡Q+눖.KʺëÌSu ‡Ñ+ìÈ–/3²ºëÌ“v +î(–0;šºËÌ“w ‘+1;jºÃÌÓx Q+ðÈ–2+JºûÈÓy Ñ+ñÈ–3+:»#ÈÓz ‡+ó–4#2»È{ ‡‘+ô¨–5 ºóÈ| ‡+öH–6#âºÓÈ} ‡ Ñ+÷ˆ–7+ªº»ÄS~ "Q+øh–8+zº«ÄS ‡$+ùˆ–93Jº›ÄS€ ‡%‘+û–:3 º‹Ä '+ü¨–;3⺓Ä‚ (Q+þH–<+꺫Àƒ *+ÿÈ–=+òº«ÀÓ„ÿ‡+‘,(–>;Òº[ÀÓ…ý‡-,H–?Cª¹ÓÀ“†û‡.Ñ,ˆ–@3й¼S‡ù‡0Q,–A Z¸{¼Sˆ÷‡2,È–Aû*·Ë¼‰õ‡3‘,H–Bë ·S¸ÓŠó‡5, ˆ–CÓò¶ë¸“‹ñ‡6‘, è–D«âµÛ¸“Œð8Q, h–E“ò´c¸Sî9‘, È–Fƒò³ƒ´SŽì‡;,(–Gsú³s´ê‡<‘,ˆ–H[´«´Óè‡>,–I+"·;´Ó‘ç?‘,¨–J *¸Ã´“’åA,(–Jó*¹´““ãB‘,h–KÛ¹k´S”á‡D,È–L«ºk´S•߇E‘,–M‹ê»¸S–݇G,H–NcÊ»;¸—Û‡H‘,ˆ–OC²»S¸˜ÚJ,–P#‚»s¸™ØK‘,H–PûR»Ë¸šÖM,H–QÛ"¼c¸S›Ô‡NÑ, ˆ–R»ú½#¸SœÒ‡PQ,!è–S›Ò¾#¸SЇQÑ,#H–Tƒª¿¸SžÏSQ,$È–Uc’¿ƒ¸“ŸÍTÑ,&h–VC‚¿“¸“ ˇVQ,'ˆ–W#b¿ƒ¸Ó¡ɇW‘,(È–XJ¿{¸Ó¢LJY,*(–XÛ*¿S¸Ó£ŇZÑ,+ˆ–YË¿3¸¤Ç\‘,-–Z«Ú¿k¼¥Â^,.h–[›²¿{¼¦À_‘,/È–\ƒ‚¿{¼§¾aQ,1H–]kb¿»¼S¨¼bÑ,2¨–^S2ÀC¼S©º‡dQ,3è–_K ÀÛ¼Sª¸‡f,5(–`;ÚÁ;ÀS«¶‡g‘,6h–a#ªÁSÀS¬´‡iQ,7È–b ‚Á#ÀS­²‡jÑ,9–cZÀ³ÀS®±lQ,:H–d2ÀkÀS¯¯m‘,;ˆ–dó ÀcÀS°­‡o,<è–e»òÀs¼S±«‡p‘,>H–f“ÒÀƒ¼S²ªqÑ,?¨–g‹²À{¼S³¨s‘,A–hƒ’À#¼S´¦‡tÑ,Bh–isj¿Ë¼Sµ¤‡v‘,D–jSB¿s¼S¶¢‡xQ,Eˆ–k;¿ ¼S· ‡yÑ,F¨–l3ê¾ë¼S¸Ÿ{Q,GÈ–m+º¿¼S¹|‘,I–n’¿+¼Sº›‡~,Jˆ–or¿;¼S»™‡Ñ,L(–oÓb¾³¸S¼—‡Q,M¨–p³:½«¸S½•‡ƒ,Nè–q£¼³¸S¾“‡„Ñ,P–r›Ò»«¸S¿‘‡†‘,QH–s‹ª»C¸SÀ‡ˆQ,RÈ–tcz»c¸“Á‡‰Ñ,TH–u;Z»+¸“ÂŒ‹Q,UÈ–vBºë¸“Ê,W(–w ºû¸“ÄˆŽ‘,Xˆ–xò»£¸ÓņQ,Yè–y ¼øÓÆ„‘Ñ,[H–yó¢½³¸ÓÇ‚“‘,\¨–zËŠ½Û¸È€‡•,^–{«b½»¸É~‡–‘,_h–|£2½›¸Ê|‡˜Q,`è–}£ ½“¸SË{™Ñ,bh–~›ò½«´SÌy›Q,cè–ƒÒ½»´“ÍwœÑ,eh–€s¢½Ã´“Îu‡žQ,fˆ–Sb¾´“Ïs‡ŸÑ,gè–‚C2¾£°ÓÐr¡Q,iˆ–ƒ+¿°ÓÑp¢Ñ,kˆ–„â¾ë°Òn‡¤Q,mH–„ó¾ðSÓl‡¥Ñ,nÈ–…Óª¾«°SÔj‡§‘,p(–†Ó¢¾3°“Õh‡©,qˆ–‡ër½«¬“ÖgªÑ,sH–ˆóR½‹¬Ó×e¬Q,u–‰Ûz½ ¬ÓØc­Ñ,vÈ–Š³b»³¬ÓÙa‡¯Q,xH–‹£º¬ Ú_‡±,yÈ–Œ£º¸«¬ Û]‡²Ñ,{h–›z·»¬ Ü[‡´‘,}(–Ž“R¶ë¬ ÝY‡¶,~è–ƒ¶«¬ ÞX·Ñ,€¨–‹"·s¬ÓßV¹Q,‚H–‘“*¸Ã¬ÓàT»,ƒè–’‹Ò¹£¬“áR¼‘,…¨–“{ª¹Ã¬“âP¾Q,‡H–”[ª¹«¬SãN‡¿Ñ,ˆè–•Cr¹«¬äL‡ÁQ,Šˆ––Kb¹ë¬åKÂÑ,Œ(–—;"º¨ÓæIÄ‘,h–˜òºS¨“çGÆ,Žè–˜ûººC¨“èEÇÑ,ˆ–™Ó¢º ¨SéC‡É‘,’(–š³b¹Ë¨SêA‡Ë,“è–››J¹Ë¤Së?‡Ì‘,•ˆ–œƒ"¹Ã¤ì>Î,—(–[ò¹³¤í<ÏÑ,˜È–ž+Ò¹{¤î:‡ÑQ,šh–Ÿ¢¹# ï8‡ÒÑ,œ(– ‚¸Ë ð7ÔQ,È– ãb¸“ ñ5ÕÑ,ŸH–¡»*¸‹ ò3ב,¡–¢‹ò¸“œó1‡Ù,¢È–£cÚ¸£œô/‡Ú‘,¤ˆ–¤S²¸»œõ.Ü,¦–¥#r¸ëœö,‡Ý‘,§¨–¥ëJ¹+œS÷*‡ß,©ˆ–¦Ã*¹{œSø)à‘,«H–§³º˜Sù'â,¬è–¨› 꺣˜Sú%‡ã‘,®¨–©s Ê»˜Sû#‡å,°ˆ–ªC ª»K˜Sü!‡æÑ,²h–« z»C˜Sý è‘,´–«Û J»#˜Sþê,µ¨–¬³ »˜“ÿëÑ,·ˆ–­ƒ ò»˜”íQ,¹ˆ–®[ »#˜”‡ï,»H–¯; Š»3˜”‡ð‘,½–° Z»;˜”‡òQ,¾È–°ë *»+˜”óÑ,À¨–±Ã » ˜”õ‘,¨–²£ ÒºÛ˜”÷,ÄH–³ƒ ¢º›œT ‡øÑ,ÅÈ–´[ zºkœT ‡úQ,Çh–µ; Rº;œT  ûÑ,Èè–¶ 2ºœT ý‘,ʨ–¶û º œT ‡ÿ,̈–·Û úºœT ˆ‘,ÎH–¸³ Òº#œT ,Ж¹“ ¢ºKœT‘,ш–ºƒ rº[œTÿˆQ,Ó(–»c JºsœTýˆÑ,Ôè–¼C º{œTûˆ‘,ÖÈ–½ òºƒœTùˆ Q,؈–½ë Òº{œø Ñ,Ú(–¾Ã ¢ºkœö Q,ÛÈ–¿“ jºS˜ô,Ýh–Àc Bº3˜òÑ,ß(–Á; ¹ã˜ðˆ‘,á(–Âò¹ƒ˜îˆQ,ã(–Âëʹ3˜íÑ,å–û¢¹˜ëQ,樖ēr¸Ó˜éˆÑ,è(–ÅsJ¸Ã˜çˆ‘,éè–ÆC"¸ã˜åˆQ,먖Çò¹3˜ÔãˆÑ,íh–Ç󹋘ÔâÑ,ïH–ÈÓ’¹Ã˜Ô à!Q,ðè–É«b¹Û˜Ô!Þ#,ò¨–Ê{2¹ã˜Ô"Ü$Ñ,ôH–ËK¹ã˜Ô#Úˆ&Q,õè–Ì#ҹØÔ$؈(,÷ˆ–Ì󪹣˜Ô%Öˆ)Ñ,ùH–ÍË‚¹“˜Ô&Ôˆ+Q,û–ΣZ¹“˜'Ó-,üÈ–Ï{2¹‹˜(Ñ.Ñ,þ¨–ÐK¹›”( Ð/Ñ-H–Ñ#â¹£”)Ï0‘-H–Ñ#ʹ«”*͈2Q-è–Ñóš¹£”+ˈ3‘-È–ÒÃr¹“”,Ê5Q-È–Ó“B¹ƒ”-È6Ñ-¨–Ôs¹{”.Æ8Ñ- H–ÕKÚ¹k”/Ä:‘- è–Ö#¢¹c”0ˆ<- ¨–Öóz¹S1Àˆ=Ñ-ˆ–×ËR¹+2¾ˆ?Q-h–Ø›"¸ó3½A-H–Ùkò¸Ë4»BÑ-–Ú;ʸÓ5¹D‘-¨–Û ¢¹Ô6·ˆF-H–ÛÛz¹ Ô7µˆGÑ-(–Ü£J¸ÛÔ8³ˆI‘-–Ýs¸sÔ9²KQ-È–ÞCâ·»Ô:°M-h–ߺ·+Ô;®NÑ- H–ßã’·Ô<¬PQ-"(–à«j·#”=ªRQ-$–á{2¶ó”>¨T-%È–âC¶{”?¦ˆU‘-'ˆ–ãÒ¶3”@¥W-)H–ãóš¶ ”A£XÑ-+(–äËjµã”B¡Z‘-,è–å‹Jµ³”CŸˆ\-.h–æCµk”Dˆ]Ñ-0H–æëÚµ#”Eœ_‘-2H–绪´Ã””Fša-4H–蛚´c””G˜ˆbÑ-5è–ékŠ´k””H–ˆdQ-7h–ê;J´›””I”ˆf-8è–ë´»””J“gÑ-:ˆ–ëòÿÚ´Ó˜”K‘iQ-<ˆ–ìÊÿ²µ˜”Lˆk->h–íŠÿšµk˜”Mˆl‘-?è–îJÿjµ“˜”N‹ˆnQ-Ah–ï"ÿ*µ£˜”OŠpQ-C–ð ÿ µS˜”PˆqÑ-DÈ–ðúþÒ´³˜TQ†ˆsQ-Fˆ–ñÚþÚ´cœTR„ˆu-HH–òªþ¢´œTSƒvÑ-Iè–ózþz´CœTTxQ-Kˆ–ôJþB´{œTUˆyÑ-M(–õþ³óœTV}ˆ{‘-N¨–õêýò³SœW|}Q-Ph–öºýʳcœXz~Ñ-R(–÷zý’³ÃœYxˆ€‘-Sè–ø:ýj³óœZvˆ‚Q-U¨–ùý:´œ[tˆ„-WH–úý³ûœ\s…‘-XÈ–úÚüâ³óœ]qˆ‡-Z(–û¢ü²³»œ^oˆˆ‘-[È–ü‚üz³cœ_nŠQ-]h–ýrüB³œÔ`lŒ-_–þJü"³œÔajÑ-`È–ÿ ûú³+œÔbhˆ‘-bˆ–ÿÂûº³#˜Ôcfˆ‘Q-dH—Šûš³#˜Ôddˆ“-eÈ—bûb³3˜Ôec”Ñ-gH—Bû³S˜Ôfa–‘-hè—úÚ³c”Ôg_˜Q-jˆ—Êúª³k”Ôh]šQ-lh—Šúz³C”Ôi[ˆ›Ñ-nH—búj³3”ÔjYˆ‘-p—Búj³3””kWˆŸQ-q¨— ú³””lV Ñ-s(—Âùâ²ó”mTˆ¢‘-tÈ—zùÒ²»”nRˆ¤-v¨— :ùв[ToQ¥Ñ-xh— ù‚²K”TpO§‘-z(— êùJ²#”TqMˆ©Q-{¨— ¢øú±Û”TrKˆªÑ-}(— Røò±ƒ”sIˆ¬‘-~È— úø²±”tH®Q-€H— Âør°Ó”uF°-‚—Šø:°‹”vDˆ±‘-ƒ¨—Zø°c”TwC³Q-…ˆ—2÷â°S”TxAµ-‡H—÷ª° ”Ty?¶‘-ˆè—Ò÷j¯Ã”Tz=ˆ¸Q-Šˆ—¢÷*¯³”T{<º-Œ—‚ö꯫”T|:»‘-¨—Jöº¯‹”}8ˆ½Q-h—öʯ“”~6ˆ¿-‘H—Òöâ¯{”4ˆÀÑ-’è—‚ö‚¯C€3ÂQ-”H—Jö2¯+Ô1Ä-•È— ö*¯Ô‚/ˆÅÑ-—ˆ—ÂõҮ댔ƒ.ÇQ-™h—‚õ¢®ûŒ”„,É-›(—Jõº¯ˆT…*ÊÑ-œè—õb¯ˆT†(ˆÌ‘-žh—ºõ*¯#ˆ‡&ˆÎQ- (—zôú¯+„ˆ%ÏÑ-¢—*ôª¯„‰#ˆÑ‘-¤—Âô‚®Ã„ÔŠ!ˆÓ-¥È—JôJ®s€Ô‹ ÔÑ-§ˆ—òô®£€ÔŒˆÖQ-©(—¢ô®ó€Ô×Ñ-ªè— Zóò¯€”ŽÙ‘-¬ˆ—! ó¢¯;€”ÛQ-®H—!²óНS€ÔˆÝ-°—"jó:¯#„Ô‘ÞQ-±ˆ—#2ó¯ „Ô’ˆßÑ-³(—#ÒòÚ¯#„Ô“á‘-´È—$jò²¯c„”ãQ-¶h—%òj¯‹„T•ˆå-¸—%²ò¯ÓˆT– ˆæ‘-¹È—&Šò °#ˆ”— ˆè‘-»ˆ—'Rò°ˆÔ˜ ê-½H—( ñê¯{ˆÔ™ˆëÑ-¿(—(ºñê®{ˆšˆí‘-Á—)zñò­+ˆT›ïQ-×*JñʬKŒTœˆðÑ-ÄÈ—+ñz¬ŒTˆò‘-Æh—+Òñ«ÓŒ”žôQ-È—,’ðÚ««Œ”ŸþõÑ-ÉÈ—-Jð²«;” üˆ÷‘-ˈ—. ðZªÓ”¡úˆùQ-Í(—.Ò𪫔¢ùúÑ-Îè—/ªï⪛Ô£÷ˆü‘-Ј—0ŠïÚª³Ô¤õˆþ-Ò(—1ZïÒª«”Ô¥ôÿÑ-Óè—2"ïjªc”Ô¦ò ‘-Õˆ—2êï*ª”Ô§ð‰Q-×h—3ªï©³”Ô¨î‰-Ù(—4jï©+”Ô©í ‘-Û—5"îò¨ƒ””ªë‰Q-ܨ—5òîÚ¨;””«ê Ñ-ÞH—6Ò“”¬è‰ ‘-ßÈ—7²î‚©”­æ‰ -áh—8jîZ©”®å Ñ-ãH—9"î:¨»”¯ã ‘-äè—9Úî ¨#”°á‰Q-æH—:’íÚ§£”±à Ñ-çè—;bí¢§+”²Þ ‘-ê—<*ír¦³Ô³܉-ì(—<òíZ¦[Ô´Û Ñ-î(—=ºír¦kÔµÙ‰‘->ríR¦£Ô¶׉-ðè—?*í ¦Ë·Ö ‘-òˆ—?êì¦ë¸Ô‰Q-ôh—@Âì’§3”T¹Ò‰!-öˆ—A’ìj§S”TºÑ "‘-øˆ—Brìb§c””»ω$-ùè—CBìB§K””¼Î %Ñ-ûH—D ì ¦û””½̉'Q-üè—Dâëʦc”Ô¾Ë )-þÈ—EÂ뚥“˜Ô¿É *‘.È—F¢ë‚¤Ó˜ÔÀlj,.¨—Grëz¤Ë˜ÔÁÆ -Ñ.¨—H:ë‚¥˜Âĉ/‘.H—I ë:¥˜Ã‰1.¨—Iúë¤ë˜ÔÄÁ 2‘. H—Jêꤓ˜ÔÅÀ 4. (—KÚꢤ;˜Ôƾ‰5‘. —LÂꪣۘÔǽ 7.¨—Mzꂣ˘ÔÈ»‰8‘.(—N*êB£ãœÔɺ :Q.È—Nòéú£«œÊ¸ ;Ñ.ˆ—OÚéÚ£;œË¶‰=Q.H—PÒéÚ¢‹œT̵ ?.È—Q¢é²¢+œTͳ‰@Ñ.(—RZé‚¢3œ”β BQ.(—S2éz¢œ”ϰ‰CÑ.(—T*éJ¡K ÔЯ EQ.è—Ué ‹ Ñ­‰FÑ.¨—Uâèê ³ TÒ«‰H‘.!h—VºèÊ¡S TÓª J.#—WºèÚ¡[ ”Ô¨‰KÑ.$È—XÊè² ƒ ”Õ§ MQ.&è—YÒ肟ˤÔÖ¥‰O.(¨—ZºèRŸë¤Ô×£‰P‘.*(—[‚è K¤ÔØ¢ RQ.+¨—\ZçÒ ƒ¤ÔÙ ‰SÑ.-(—]b窠“¤ÔÚŸ‰UQ..è—^jçr ³¤ÔÛ‰VÑ.0è—_Zç Ó¤ÔÜœ X‘.2¨—`:檠㤔ݚ‰ZQ.4(—aæj¡¤”Þ™ [Ñ.5¨—bæZ¡3¤”ß— ]‘.7(—cæJ ó¤”à•‰_.9—d æ ƒ ”á” `‘.:È—dúåâ c Tâ’‰b.h—fªåª [ Tä‰eQ.@h—gj媠 TåŽ fÑ.B—h:åzŸ³ T按hQ.C¨—i*å"Ÿs Tç‹ iÑ.Eˆ—j2埓 T艉k‘.GH—k2åŸÓœT鈉m.I—l äÚ Kœê‡ nQ.Jè—lÚ䢠ãœë…‰p.Lˆ—mÒ䢡œì„ q‘.Nh—nÚäâ »œí‚‰s.P—oºäú ‹œî t‘.Q¨—pz䪡s˜ï‰v.SH—q2äB£s˜Tð~ w‘.U(—qúãò¥ ˜Tñ|‰y.Vè—rêãÚ¥£˜Tò{ zÑ.X¨—sêä ¥ã˜”óy‰|‘.ZH—tÚä"¦˜”ôx ~.\(—u¢ãÊ¥Û”Ôõv‰‘.^(—vrã’¥[”Ôöu .`H—wbãò¤«” ÷s‰‚Ñ.bH—xbäJ£+” ør „Q.d—yJä: ›” Tùp‰…Ñ.eè—z"ä*žë” Túo ‡Q.gè—zúãú “” Tûm‰‰.j—{Òãº¤ó” ”ül ŠÑ.l(—|²ãŠªÓ” ”ýj‰ŒQ.n—}šã‚­K” ”þi Ñ.oè—~’ã’­S” ”ÿg‰Q.q¨—‚㲬+” •f Ñ.s¨—€jãš©›” •d‰’‘.uˆ—Jãj¦³” •c ”.wˆ—‚ã*¥{” •a‰•‘.yˆ—ƒâÂ¥£” •` —.{¨—ƒÚâZ¦«” •^‰˜‘.}ˆ—„ºâ §Ã” •] šQ.H—…¢áÚ¨;˜ •[‰œ.€è—†’Ẩƒ˜ •Z ‘.‚È—‡Šá¨»˜ • X‰ŸQ.„È—ˆ‚á⩜ • W  Ñ.†è—‰rá⩳œ Õ U‰¢Q.ˆ¨—ŠRኪC  Õ T £Ñ.Š—‹2á"« ! S ¥Q.‹ˆ—Œàâ¬c !UQ‰¦Ñ.H—àâ­¤!•P ¨Q.(—Žàꬫ¤!ÕN‰ª.‘(—àÊ«³¤"L‰«Ñ.“—àŠª£¤"•K ­Q.”è—‘à*©£¤"ÕI‰¯.–ˆ—’à¨[¤#H‰°‘.˜h—“Bàb¦S¤#•G ².šˆ—”jàú£3¤#ÕE ³Ñ.œˆ—•zár £¤$D µQ.žH—–záR S¤$UB‰¶Ñ. (——Šá «¤$UA ¸.¢(—˜¢á*¡¤$•?‰¹Ñ.¤ˆ—™ºá*¡ $•>‰».¦È—šºá ë $Õ= ¼Ñ.¨ˆ—›Âàê¡ $Õ;‰¾Q.ªh—œÒມC %: ¿Ñ.¬h—âàŠ¡Kœ%9 ÁQ.®¨—žúàj¡+œ% 7‰ÂÑ.°È—ŸòàR¡œ%!6 Ä.²È— òàR¡˜%U"4‰Å‘.´¨—¢ à:¡˜%U#3 ÇQ.¶È—£*ßú Ã˜%U$2 ÈÑ.¹(—¤:ßÊ ƒ”%•%0 Ê‘.»¨—¥Bß² K”%•&.‰Ì.½è—¦Bߪ C”%•'-‰Í‘.À—§Jߊ 3”%Õ(, ÏQ.Â(—¨ZßZ %Õ)*‰ÐÑ.Ĉ—©bßB %Õ*) Ò‘.Ç—ªJß2 ‹%Õ+' ÔQ.Éh—«JßJ¡£&,& ÕÑ.˨—¬bßZ£k&-$‰×Q.ÍÈ—­rß"¥k&.# Ù.ÏÈ—®Šß"¦›&/!‰Ú‘.Òh—¯zÞê¦c&0 ÜQ.Õ—°jÞ²¤ã&1‰Þ.×h—±jÞ¢¢Ó&U2 ßÑ.Ùˆ—²‚Þz¢&U3‰áQ.Ûˆ—³¢Þr¢{&U4 âÑ.Ýè—´²Þ£+&U5‰ä‘.àH—µ²Ýʤ &U6 æ.⨗¶ªÝš¤s”&•7‰çÑ.å—·ÂÝb¤£”&•8 éQ.ç(—¸âÝ*¤ã”&•9‰ë.éH—¹òÝ¥c”&•: ì‘.눗»ÜÒ¥ë”&Õ;‰îQ.íÈ—¼Ü¢¦K”&Õ< ïÑ.ð—½*Ür¦˜&Õ= ‰ñ‘.ò(—¾BÜ:¥{˜&Õ> ó.ôh—¿Rܤû˜&Õ? ‰ôÑ.ö¨—ÀZÛò¤‹˜'@ ö‘.ù—ÁzÛÊ£û˜'A‰ø.ûH—¢ۢ£#˜'B ùÑ.ýH—ÃÊÛr¢;˜'C ûQ.ÿˆ—ÄâÛJ¡Ó˜'D‰üÑ/È—ÅúۡØ'E þQ/(—ÇÚê¡ó˜'F ÿÑ/ˆ—È:Ú²¢˜'GþŠQ/È—ÉRÚ‚¢;˜'Hý / (—ÊZÚJ¢[˜'IûŠÑ/ ˆ—ËJÚ¢[˜'Jú Q/È—ÌRÙâ¢K˜'KøŠ/(—ÍjÙ²¢˜&ÕL÷ Ñ/h—Î’Ùr¡ã˜&ÕMõŠ ‘/¨—ϲÙJ¢ ”&ÕNô /è—ÐÊÙ*¢3”&ÕOòŠÑ/H—ÑÒØò¢C”&ÕPñ Q/¨—ÒÚØº¢3”&ÕQïŠÑ/è—ÓêØŠ¢#”&ÕRî ‘/!è—ÕØR¢”&•SìŠ/$—ÖØ"¡ë”&•Të Ñ/&H—×*×ê¡Û”&•U銑/(È—Ø:סӔ&•Vè Q/+(—ÙBך¡Ó”&•WæŠÑ/-ˆ—ÚJ×Z¡Ã”&•X劑//¨—Ûj×"¡Ë”&•Yä /1È—ÜzÖú¡ã”&•Z⊠Ñ/3è—݂֢#”&•[á "‘/6H—Þ’Öš¢{&Õ\ߊ$/8¨—ß’ÖR¢Û&Õ]Þ %Ñ/:è—àšÖ£Ë'^ÜŠ'‘/=(—á¢Õò¥C'^ Ü (/=(—á¢Õ⥻'_Û )/?¨—âºÕʦ“'U`ÙŠ*Ñ/B—ãÚÕ‚§'•aØ ,Q/Dh—äòÕB§3'•b× ./FÈ—åúÕ2§['ÕcÕŠ/‘/I(—ç Ôâ§K(dÔ 1Q/Kˆ—è:ÔŠ§SŒ(UeÒŠ2Ñ/N—ébÔj§CŒ(UfÑ 4Q/P¨—êzÔj¦[Œ(•gÏŠ6/S(—ëzÔb¤£Œ(ÕhΊ7‘/Uˆ—ì‚ÔB¢{Œ(ÕiÍ 9Q/WÈ—í¢Ô  ÓŒ)jËŠ:Ñ/Zh—îÒÓâŸÓˆ)kÊ *Æ¢˜Ûx-U´c µ‘0&h˜?JÆÂ˜#x-UµaŠ·Q0)ˆ˜@ZÆz—t-•¶` ¹0,ˆ˜AjÆ"–[t-•·^Šº‘00˜BŠÅò–t-Õ¸]мQ03H˜C¢Å•ût-Õ¹\ ¾06H˜D²Å¢–t-ÕºZŠ¿Ñ09h˜EÒÅz•ót-Õ»Y ÁQ0 âÑ0yh˜\úÁÚ—Ëx-•Ð<Šä‘0|ˆ˜^Á¢—Ëx-•Ñ; æQ0¨˜_BÁj—Óx-•Ò9Šè0‚Ș`bÁ:—Ãx-•Ó8 éÑ0…è˜ajÁ —Ãx-UÔ7 ë‘0‰(˜b‚Àâ—»x-UÕ5Ší0Œ(˜c¢Àº—Ãx-UÖ4 îÑ0Žè˜dÊÀr—Ëx-U×2Šð‘0‘ȘeúÀ2—Ëx-UØ1ŠòQ0”Șg À*˜ x-UÙ0 ôQ0˜˜h¿ú˜#|-Ú.Šö0›H˜i¿²˜+|-Û- ÷‘0ž(˜j2¿’˜c|-Ü+ŠùQ0 è˜kb¿B˜[|-Ý* ûQ0£ˆ˜lŠ¾Ú˜S€-Þ(Šý0¦¨˜m²¾º˜›€-ß' þÑ0©è˜n¾¢˜ë€-à%‹Ñ0¬è˜oâ¾J˜Û€-á$‹Q0¯¨˜q½ò˜£„-â# 0²H˜rZ½ò˜“„-ã!‹Ñ0µ˜s’¾˜k„-ä ‹Q0¸˜tª½â˜„-å 0»(˜uÚ¾"˜+„-æ‹ Ñ0½è˜w"¾ —ã„-ç‹ ‘0À¨˜xR½¢—s€-è 0Ãh˜yr½z—C€-é‹Ñ0ƈ˜zš½z—#€-ê‹‘0Éh˜{º½j–Ó€-ë 0Ëè˜|ò½B–s|-ì‹Ñ0Ψ˜~"½–K|-í‹‘0ш˜*¼º–C|-î Q0ÔȘ€2¼J–#x-ï‹0×ȘJ»ú–x-Uð‹‘0Û˜‚z¼–;x-Uñ ‘0ÞH˜ƒ¢¼R–;t-Uò ‹Q0ᘄ¼b•ót-•ó !0ã蘅ڼJ•›t-•ô ‹"Ñ0æè˜†ò»ò•Kt-Õõ $Ñ0ê(˜‡ò»z•+p.ö‹&‘0íH˜ˆò»•+p.÷‹(Q0ð(˜Šºú•Cp.Uø *0óH˜‹Jºâ•3p.•ù‹+Ñ0öh˜Œrº¢”Ûl.Õú -‘0ùȘ‚ºb”“l.Õû /Q0ýH˜Ž’ºB”‹l/üÿ‹0Ñ1ˆ˜¢º”“l/Uýþ 2‘1Șª¹Ê”›h/Õþý 4Q1˜‘²¹Š”³h0ÿû‹5Ñ1 ¨˜’ʹš•h0Vú‹7Ñ1H˜“Ú¹ª•h0–ù 9Q1¨˜”â¹r”Ëh0Ö÷‹;1蘕ê¹”ch1Vö‹<Ñ1H˜–ú¸Ú“óh1–õ >‘1蘘:¸ê“£h1Öó‹@1¨˜™b¸ò“3h2Vò‹AÑ1#¨˜šj¸º’{h2–ñ C‘1'H˜›š¸’‘ãh2Öï‹EQ1*¨˜œâ¸¢‘£l3 î‹G1-蘞¸r‘l3V í HÑ11h˜ŸB¸:ƒl3– ì JQ15H˜ j¸bSp3Ö ê‹KÑ19(˜¡ª¸Ò+p3Ö é M‘1<Ș¢ò¸Êƒp4è OQ1@(˜¤2¸šŽãp4ç PÑ1Cˆ˜¥r¸JŽst4Vå‹R‘1G˜¦º·âŽ+t4Vä TQ1J¨˜§ú·ŠŽt4Vã V1Nh˜©2·ZŽ#t4V â W1Q蘪r·JŽ3x4Vá‹WÑ1Q蘪r·:ŽCx4Và Y‘1U(˜«º·:Ž[x4VÞ‹[Q1XH˜­·:ŽCx4VÝ‹]1[ˆ˜®J·JŽx4VÜ ^Ñ1_H˜¯’·"‹|4VÛ `Q1bȘ°ê¶Ò |4VÙ‹b1f(˜²B¶ŠŒ»|4VØ d1iˆ˜³ª¶rŒÃ|4V× eÑ1m˜´ò¶ZŒë|4VÕ‹gQ1pH˜¶B¶"Œû|4VÔ‹i1s¨˜·’µÚŒë|4Ó jÑ1wH˜¸ò¶ |4Ñ‹l‘1zȘºJ¶2;|3Ö ЋnQ1~(˜»’µòŒë|3Ö!Ï oÑ1h˜¼ÚµšŒc|3–"Í‹q‘1„Ș¾"µr‹ë|3–#Ì‹sQ1ˆ˜¿bµZ‹s|3–$Ë u1‹h˜À¢µJŠã|3V%Ê v‘1ŽÈ˜ÁÚµ"ŠC|3V&É xQ1‘è˜Ã"´ú‰Ã€3V'Ç‹yÑ1•(˜Äjµ‰³€3–(Æ {‘1˜h˜Åº´ê‰[€3–)Å }Q1›¨˜Ç ´Š‰€3–*Ä ~Ñ1Ÿ(˜Èb´ ‰+€3Ö+‹€‘1¢h˜É²³Â‰›€3Ö,Á‹‚Q1¥È˜Ë³ªŠK|3Ö-À ƒÑ1©H˜ÌR³ªŠã|4.¾‹…‘1¬È˜Í¢³š‹c|4/½‹‡1°H˜Îò³r‹£|40¼‹ˆÑ1³È˜ÐB³J‹{|41» ŠQ1·(˜Ñ¢³J‹#|42º ‹Ñ1º¨˜Ó ³‚ŠÃ|43¹ Q1½è˜ÔR³¢Šx3Ö4·‹1Á˜Õ’³²‰kx3Ö5¶‹‘1ÄH˜ÖÚ³ŠˆËx3Ö6µ ’Q1Çè˜Ø"³"ˆt3–7´ ”1ˈ˜ÙZ²â‡‹t3–8²‹•Ñ1Ï(˜Ú¢³‡Cp3V9±‹—Q1Òˆ˜ÛÒ³J†»p3V:°‹™1Õè˜Üú³*…Ãl3;¯ š‘1Ùˆ˜Þ*²ú„ól3<­‹œ‘1ÝH˜ßj³2„£h3=¬‹ž1àˆ˜à¢³"„ h2Ö>« ŸÑ1ä˜áº²ºƒsh2Ö?ª ¡‘1稘âÒ²¢ƒKd2Ö@¨‹£1ëȘãê²¢ƒSd2ÖA§‹¤Ñ1ïh˜äâ²jƒd2ÖB¦ ¦‘1ó˜åú²Z‚û`2ÖC¥ ¨1ö¨˜ç"²B‚Û`2ÖD¤ ©Ñ1úH˜è2²"‚£`2ÖE¢‹«‘1ýè˜éJ²*‚£`3F¡‹­Q2ˆ˜êR±â‚k`3VG  ®Ñ2H˜ëZ±¢‚K`3VHŸ °Ñ2è˜ìr±j‚C`3–I‹²‘2 ¨˜í’±B‚3`3ÖJœ ´Q2h˜îª±*‚#`4K› µÑ2H˜ï±"‚#`4VLš ·‘2(˜ðò± ‚`4–M˜‹¹Q2˜ò"°Úë`4ÖN—‹ºÑ2è˜óR°ºë`5O– ¼‘2#Șôr°²‚ `5P• ¾Q2'Șõаª‚+`5VQ“‹À2+¨˜öš°j‚#`5–R’‹ÁÑ2/ˆ˜÷°J‚3`5ÖS‘ ÃQ23(˜øò°J‚S`6T Å27(˜ú"°*‚S`6VUŽ‹ÆÑ2;(˜ûB° ‚k`6–V‹È‘2?H˜üZ¯ò‚£`6ÖWŒ‹Ê2Ch˜ý‚¯âƒ`7X‹ ËÑ2Gh˜þº¯ºƒ›`7YŠ Í‘2Kh™¯’„3`7VZˆ‹Ï2Oh™:¯z„ã`7–[‡‹ÐÑ2Sˆ™Z¯Z…ƒ`7Ö\†‹ÒQ2Wˆ™‚¯:†`7Ö]… Ô2[¨™¢¯*†s`8^„ ÕÑ2_è™Ò¯†»`8_‚‹×‘2d™ ®ú†Ã`8V`‹ÙQ2h™:®ê†›`8Va€ ÚÑ2l™ j®ª†3`8–b Ü‘2oè™ ²®r…³d8–c}‹Þ‘2t(™ ®B…d8–d|‹à2xh™ R®2„«d8–e{ áÑ2|ˆ™ª®z„›d8–fz ã‘2€h™Ú®z„Sh8Ögx‹åQ2„¨™ ®Bƒóh8Öhw‹ç2ˆ¨™B­òƒ›h8Öiv‹èÑ2Œè™š­¢ƒSh8Öju ê‘2‘™ò­jƒ#l8Ökt ìQ2”è™Z­J‚ûl8Ölr‹î2˜ˆ™š­R‚ãl8Ömq‹ïÑ2œh™Ú­Z‚Ãp8Önp ñ‘2 H™:­ ‚Kp9oo óQ2¤™ЬªËt9pm‹õ2§è™ê¬zƒt9Vql‹öÑ2«¨™R¬Šsx9–rk‹øQ2¯h™¢¬B€ûx:sj ú2³H™! ¬ €›x:Vti ûÑ2·H™"š¬€S|:Öug‹ý‘2»(™$*«òÃ|;vf‹ÿQ2¿™%²«Ú|;–we 2ÂÈ™':¬ ~‹€<xd Ñ2Æh™(ª¬ }Û€<–ybŒ‘2ÊH™*:¬*}ƒ€<ÖzaŒQ2ÎH™+⬂}³€=V{` 2ÒH™-‚¬ê~3€=Ö|_ 2ÖH™/2­J~û€>}]Œ Ñ2Ú(™0Ú­B»€>V~\Œ ‘2ÞH™2r­*€›€>Ö[ Q2âh™4­K€?€Z 2戙5š¬êã€?VY Ñ2êH™7R­‚{€?–‚WŒQ2îH™8ò¬Ú‚£€?ÖƒVŒ2òˆ™:z¬z‚£€?Ö„UŒÑ2öè™<¬r‚Ó€@…T ‘2ûh™=Ò¬r‚ó€@†S Q2ÿh™?ЬZ‚Ë„@V‡QŒ3h™A2¬Z‚“„@VˆPŒÑ3H™BÒ¬j‚[„@V‰O ‘3 h™Dr¬Z‚„@VŠN "Q3ˆ™F¬*£„@V‹M $3¨™GÚ«º+„@VŒKŒ%Ñ3¨™I’«R€Ó„@VJŒ'Q3ˆ™K:«*€³„@VŽIŒ)3ˆ™Lò«J€Ë„@H *Ñ3#ˆ™Nš«J€Ó„@G ,‘3'È™P:«€“„@‘F .Q3+È™Q⪺€c„@’DŒ03/ˆ™S’ªš€s„@“CŒ1Ñ33¨™U:ªb€c„?Ö”B 3‘37È™VÚª€C„?Ö•A 5Q3;è™XŠª€[„@–@ 6Ñ3?è™Z:ªJ€‹„@—? 8Q3C¨™[ʪB€c„@˜> 9Ñ3Gˆ™]Rª:€„@™<Œ;Ñ3Kh™_ªbë„@Vš;Œ=‘3Oˆ™`ªb“„@V›:Œ?Q3SÈ™bzªJK„@Vœ9 A3X™d2©ê~Û„@–8 BÑ3\H™eÚ©¢~c„@–ž6ŒD‘3`H™gz©’~k„@ÖŸ5ŒF3dH™i*©Z~{„@Ö 4ŒGÑ3hˆ™jÚ© ~{„A¡3 I‘3lÈ™l’¨Ú~£„A¢2 K‘3q(™n:¨º~ÄAV£1 MQ3uH™oÒ¨š~Ó„AV¤/ŒO3yh™qz¨š~ó„A–¥.ŒPÑ3}h™sB¨r~ë„A–¦-ŒR‘3ˆ™u¨B~Ó„AÖ§, TQ3†™vº¨ ~³„AÖ¨+ V3ŠH™xj§ê~»€B©* WÑ3Žˆ™z"¨"€Bª(ŒY‘3’¨™{Ò¨ +€BV«'Œ[3–è™}Ч’~Û€BV¬&Œ\Ñ3›(™:§J~Ë€BV­% ^Ñ3Ÿˆ™€ú§2~Û€B–®$ `‘3£è™‚ª¦ú~«€B–¯"ŒbQ3¨H™„Z¦Â~s€B–°!ŒdQ3¬ˆ™† ¦Ò~{€B–± Œf3°È™‡Â§ ~ƒ€B–² gÑ3µ(™‰r¦Ò~#|BÖ³ i‘3¹h™‹¦š}Ë|BÖ´ŒkQ3½È™Œº¦’}«|BÖµŒm3Âh™ŽR¦j}S|BÖ¶ŒnÑ3Ç™â¦J}|BÖ·Œp‘3Ëh™‘š¦J}|C¸ rQ3Й“Z¦"|Ë|C¹ t3Ôh™•¦*|ã|Cº u‘3ب™–Ú¦r}[|C»Œw‘3Ü虘‚¦:}k|BÖ¼ŒyQ3á(™š*¥Â}S|BÖ½Œ{3å(™›â¥z}S€BÖ¾ |Ñ3鈙ª¥j}k€B–¿ ~‘3z¥Š}“€B–À €Q3òˆ™¡"¥š}ƒ|BVÁ ‚3öÈ™¢²¥z};|B Œƒ‘3û™¤R¥:|Ë|Bà Œ…Q3ÿh™¦ ¤ê{ó|AÖÄ Œ‡4È™§Ê¤Ú{|AÖÅ ŒˆÑ4™©j¥zS|A–Æ Š‘4 (™ªê¥"y#|A–Ç ŒQ4h™¬r¤ÊwC|A–È Ž4¨™®¤‚u;|A–É ‘4™¯¢¤šs{xA–Ê ‘Q4h™±b¤úrxA–ËŒ“4!È™²ê¥BpãxA–ÌŒ”Ñ4&ˆ™´r¥*o‹xA–ÍŒ–‘4+H™¶¤ún[xA–ÎÿŒ˜4/h™·’¤ÒmÛxA–Ïþ š43h™¹B¤ênKxA–Ðý ›Ñ47¨™ºú¤ÒnËxA–Ñü Q4<(™¼¢¤¢o#xAVÒû Ÿ4@¨™¾B¤ÊoÓxAVÓùŒ¡4D虿ڤ’oãxAVÔøŒ¢Ñ4I™Á‚¤zoËxAÕ÷Œ¤‘4MH™Ã2¤boƒxAÖö ¦Q4Qˆ™ÄÒ¤nëx@Ö×õ ¨4U¨™Æj¤JnÃx@ÖØô ©Ñ4Yè™Çú¤jn{x@–Ùó «‘4^H™É‚¤:mûx@–Úò ­4bˆ™Ë¤Jmët@–Ûñ ®Ñ4fè™Ìª¤¢nCt@VÜð °‘4kˆ™Î:¤Šn+t@VÝQ4p™Ïʤ*mÓt@VÞ팳Ñ4tH™ÑR£òm«p@ß쌵‘4x¨™Òê¤JmÃp@à댷Q4}™Ôj¤jmƒp@áꌹ4ˆ™Õʤ l³p?Öâ錺Ñ4†™×:£Úll?Öã茼Q4Šˆ™Øº¤"kël?Öã è ¼Ñ4Šˆ™Øº¤kÓl?Öäç ¾4™Ú:¤kkl?–åæ ¿Ñ4“ˆ™Ûº£¢j³l?–æå Á‘4—è™Ý*£ºjƒl?–çä ÃQ4œ(™Þš¤"j“l?Vèã Å4 ¨™ßú¤Rj[l?Véâ Æ‘4¥™áb¤*i»l?VêàŒÈQ4©¨™âÚ¤il?ëߌÊ4­è™äB£òh3l?ìތˑ4²(™åŠ£êgcl?íÝŒÍ4¶¨™æú¤Zg l?îÜŒÎÑ4»™èŠ¥bgcp?ïیБ4¿h™ê¥Òg3p?ðÚŒÒ4Ãș몥Šfkp?Vñٌӑ4Çè™í*¥šfp?VòØŒÕQ4̙²eût?Vó׌×4Ðh™ð ¥Reƒt?–ô֌ؑ4ÔÈ™ñŠ¥"e[t?–õՌڑ4Ù(™ó*¥eSt?ÖöÔŒÜ4ݨ™ôʤòe+t?Ö÷ÓŒÝÑ4áÈ™öB¤Âdãt@øÒ ß‘4åè™÷Ò¤šd›t@ùÑ áQ4êH™ùr¤jd+t@VúÐ âÑ4û ¤Zc£t@VûÏ ä‘4òè™üª¤úc£t@–üÎ æQ4÷h™þJ¥jc[t@–ýÍ è4û¨™ÿâ¥:bkt@–þÌ éÑ5šj¥jaãt@–ÿË ë‘5ˆšâ¥âaÃt@WÉŒí‘5 Hšj¦*aƒp@WÈŒïQ5 Èšú¦2a#p@ÇŒñ5š‚¦`óp?ׯŒòÑ5hš ¦`óp?—ÅŒôÑ5Èš š¦Ba;p?WÄ ö‘5𠦂a{p?à øQ5#ˆš Цracl>— ú5(šò¦`ël>WÁ ûÑ5,HšJ¥Â`[l> À ý‘50hš²¥²` l=— ¿ ÿQ54ˆš*¥ò`l=W ¾ 59š’¦ _Ûl= ¼Ñ5=hšú¥²_sl<× »Ñ5A¨šJ¥J^ûl<—º‘5EÈš²¥R^ûlW"¦ )Q5›ˆš3¢¤Ò]+h>—#¥ +5Ÿ¨š5¤Š] h>×$¤ ,Ñ5¤Hš6‚¤r]+h?%¢.‘5¨èš7ú¤Z]ch?W&¡0Q5­ˆš9r¤’]Ëh?—' 25²(š:ê¥J^‹l?×(Ÿ3Ñ5¶¨šQ5ÑèšE¥r^St@W/˜@5ÖšF²¥Ò^Kt@W0—AÑ5ÚšHb¦2^;t@W1–CQ5ÞšJ¦j]Ût@—2•E5âhšK¢¦š]³x@—3”G5æèšM*¦Â]{x@—4“H‘5ë(šNʦê]Sx@—5’JQ5ï(šPr§]Kx@×6‘LQ5óˆšR"§š]‹x@×7N5øšSº¨]Û|@×8OÑ5ühšUB¨]£|A9ŽQQ6èšV§¢] |A:SQ6HšXJ§’\³|A;ŒTÑ6 ˆšYò§ê\“€A<‹V‘6 ¨š[ª§Ò\€A=ŠXQ6š]J§²[“„@×>‰ZQ6hš_¨ [K„@×?ˆ\6hš`ʨš[ „@—@‡]Ñ6ˆšbЍâZ«ˆ@WA†_‘6"HšdJ©JZ‹ˆ@WB…a6&hšeò©šZ{Œ@C… b‘6*hšgªªZÓŒ?×D„ dQ6.(šiRª[?—Eƒ f62šk ª2[K?WF‚ gÑ65¨šlÒªb[›”?G i‘69(šnŠª[S˜>×H€ k‘6<èšp2©Â[ ˜>—I mQ6@hšqú©¢Zûœ>WJ~ o6CÈšs©zZÜ>K} pÑ6GHšu’©JZS =—L| rQ6Jèšwb©YÛ =WM{ t6NšyR©ZY‹ <×Nz uÑ6QHš{*©zY¤<—Oy w‘6Tˆš|ê©‚XS¤<Px y6Xš~ªªX¤;—Qwz‘6[š€j«X;¤;WRv|Q6]èš‚*«¢X¤:×Su~6`蚃ò«ÚW£¤:WTtÑ6dš…²«êWk¤:UsQ6gHš‡b¬Wc¤9—Vrƒ6jˆšˆú¬bW‹¤9WWq„Ñ6mhšŠ¢¬âWÛ¤9Xp†‘6phšŒb­rX3 8×Yp ˆQ6s¨šŽ­’X 8—Zo ‰Ñ6vÈšš­‚Wã 8W[n ‹Ñ6yÈš‘2­òWûœ8W\m ‘6}š’Ê­úWÛœ8]l Q6€Hš”Z­ÚW³œ8^k ‘Q6ƒˆš•ú­âW³˜8_j “6†èš—’­êW«˜7×`i ”Ñ6Šš™*­úW‹˜7×ah –‘6hššº­âWS˜7—bg ˜6¨šœ:­²VÛ˜7Wcf ™Ñ6”(šº­’Vc”7de›‘6—hšŸ2­ºV3”6×ed6š¨š Â­ÂUÓ”6—fcžÑ6Èš¢R­ºUƒ”6Wgb ‘6¡š£ê­ÂUC”6ha¢6¤š¥r®U#”5×ia ¤6§š¦Ú®ºUC”5×j` ¥‘6ªHš¨:¯U#”5—k_ §Q6­ˆš©š¯‚U;”5—l^ ©6°¨š«¯úU3”5Wm] ªÑ6³Èš¬Š°JUK”5Wn\ ¬‘6¶Èš®"°ŠUs”5Wo[®Q6¹èš¯š°²Us”5—pZ°6¼èš± ±ZU³”5—qY±Ñ6À(š²r±zU£”5—rX³‘6Ã(š³ê±RU[”5×sWµQ6ÆHšµŠ±RU;”5×tV¶Ñ6Ɉš·*±ÒUS”5×uV ¸‘6Ì蚸º²*Uƒ”5×vU ºQ6ÐHšºB²zUë”5×wT ¼6ÓH𻲲ªUÓ”5—xS ½‘6ÖHš½*²ÚU›”5—yR ¿‘6Ùˆš¾ª²ÒUS˜5WzQ ÁQ6ÜÈšÀ*²ÂU˜5{PÂÑ6àšÁ²òU˜4×|OÄÑ6ã(šÃR³jU{˜4—}NÆ‘6æ(šÄ²³ÒV˜4W~MÈQ6é(𠨬:V«˜3×LÊ6ìšÇ‚´rVÓ˜3—€KËÑ6É´rV›œ3WJÍ‘6ñhšÊ‚´zV;œ3W‚J ÏQ6ôˆšÌ´’UÛœ3ƒI Ñ6÷hšÍj´ªUcœ3„H ÒÑ6ú(šÎÚ´ÊTëœ2×…G Ô‘6ü¨šÐJ´êTËœ2׆FÖQ6ÿHšÑʵTËœ3‡EØ7HšÓBµ*Uœ3ˆDÙÑ7HšÔšµbUsœ3W‰CÛQ7HšÕêµÂV˜3—ŠBÝ7 Hš×j¶ W˜3׋B ß7(šØúµâW³˜4ŒA àÑ7HšÚjµªWó˜4W@ â‘7HšÛâµjW»˜4—Ž? äQ7HšÝJµ"WK˜4×> åÑ7hšÞÊ´êVÛ˜5=ç‘7¨šàR´ºVË”5W‘<éQ7 ¨šáâ´ªVÛ”5—’;ë7#ˆšãŠ´ÂVã”5—“:ìÑ7&èšå ´¢VÔ5×”: î‘7*Hšær´ŠV£5ו9 ðQ7-Hšçú´ºV[5×–8 ñÑ70ˆšéz´¢UÛ5×—7ó‘73Èšêê´âUã5ט6õQ77hšìJµ*VŒ5—™5÷7:èší¢µjVKŒ5—š4øÑ7>HšïµÂVkŒ5W›4 úQ7Ahšðzµ²V+Œ5œ3 ü7DhšñúµâVŒ4×2 ý‘7G¨šób¶JVsŒ4—ž1ÿQ7KHšôº¶rVË4WŸ0Ž7NÈšö ¶jVë4 /Ž7QÈš÷z¶’W3ס.Ž‘7TÈšøú¶bVã3W¢.Q7Wèšúj¶"V‹”3£-7ZèšûÒ¶RV£”2—¤, Ñ7]èšýB¶šVó”2W¥+Ž Q7`¨šþ¢¶rVË”2¦*Ž Q7cˆ› ¶BV{”1—§)ŽQ7f(›z¶bVs˜1W¨(ŽÑ7hțڶªV‹˜1©'Ž‘7kˆ›*¶ªVs˜0—ª'Q7nˆ›z¶bV˜0W«&Ñ7qh›º¶*U«˜/׬%‘7tH›¶bU˘/—­$ŽQ7wh› z¶ÊV3˜/®#Ž7z(› Ò·V«˜.ׯ"ŽÑ7|È› *·*VÛ˜.W°"‘7H› Š·:V³˜-×±! Q7è›Ò·*V#˜-—² "7„H›·BU«˜-³$7†¨›j·²Us˜,—´%Ñ7‰(›ª·òUs˜,WµŽ'Q7‹È›â·òUƒ”,¶Ž)7Žh›·ÒU«”+×·Ž+7‘›·ÂUÛ”+—¸,Ñ7“H›B¸V +W¹.‘7•h›Џ"VC+Wº0Q7—è›Ê·êVKŒ+W»Ž27šè›â·âUûŒ+W¼Ž3Ñ7ž›ò¸U“ˆ+—½Ž5‘7 È›¸‚UÈ+—¾Ž7Q7¢è›:¸ÚV3ˆ+׿97¥H›j¸¢Vƒ„,À:Ñ7¨H› ‚¸RV£„,WÁ<‘7«È›!¢¸*VÓ€,—Â>‘7®È›"â¸ZW€-ÃŽ@Q7±ˆ›$¸rW;€-WÄŽB7´H›%¸ZW[|-×ÅŽCÑ7·(›&:¸W3|.ÆE‘7º¨›'b·ÂVë|.—ÇG7¾H›(‚·zV³|.×È HÑ7Áh›)ª·2V“|/WÉ ŽJÑ7ÄH›*Ò· V;|/—Ê ŽL‘7Çh›+ú¶êUÓ|0Ë ŽNQ7ʨ›-*¶ÒU“|0WÌ OÑ7Íè›.j·U“|0×Í Q‘7Ñ›/º·ŠU³|1ÎS‘7Ô(›1·BUk|1WÏŽU7×H›2*·:U3x1—ÐŽVÑ7Úˆ›3b·šU‹x1—ÑŽX‘7Þ(›4¢·‚Uãx1×ÒZQ7ᨛ5ò·JVx1×Ó\7äè›7R·’Vsx1×ÔŽ]Ñ7è›8š·²V£x1×ÕŽ_Q7ëh›9Ê·jV‹x1—ÖŽa7îÈ›:â·:V[x1—×c7òH›<·:V;x1WØd‘7õ¨›=Z·*V;t1ÙÿfQ7øÈ›>¢·RV[t0×ÚþŽhQ7ü›?Ú·:Vst0WÛýŽj7ÿ(›@ê·V{t0ÜüŽkÑ8ˆ›Aò· Vƒt/×ÝümQ8è›C¶ÊVSp/—Þûo8 (›DR¶²Vsp/WßúŽpÑ8 ˆ›E‚¶ŠV»p/àùŽrÑ8È›FжjVÛp.×áøŽtÑ8è›G’¶ZV«l.—â÷Žv‘8è›H’¶Vsl.—ã÷x8è›IºµâV[l.—äöyÑ8(›Jʵ²VKh.—åõŽ{‘8H›KµªV h.׿ôŽ}Q8"h›L²µšUÓh/çóŽ8%ˆ›M²µrU›d/WèòŽ8(è›NºµZU[d/—éò‚Ñ8,h›OÒµjUSd0êñ„Ñ80(›PòµŠUKd0Wëð†‘83è›RµªUc`0×ìQ87¨›SµÒU³`1Wí8;(›T2¶2V#`1—í î‹Q8>È›U*¶2V;`2îî‹Ñ8>È›U*¶2VC`2ïí‘8BH›V2µÒV#`2WðìQ8Eè›WbµšV `2—ñëŽÑ8IÈ›X‚µjV`2×òꎒÑ8Mh›Y¢µJUÓ\3ó鎔‘8Q›Z²µ*U‹\3ôé–Q8TÈ›[ʵU\3Wõè—Ñ8X¨›\â´òTË\3Wö玙‘8\¨›]ú´úT«\3W÷掛Q8`ˆ›_ µTÛ\3Wøæ8dh›`µZUX3ùåžÑ8h›a2µšUSX3úä Ñ8kÈ›b:µŠU“X2×û㎢‘8o¨›cBµjUËX2×ü⎤‘8s¨›dBµBUëX2—ýᎦ8wH›eJµU»T2—þá§Ñ8{›fZ´âUST2Wÿà©‘8~¨›gZ´ÒUT2Xߎ«Q8‚ˆ›hB´ºTóT2ÞŽ­8†h›i:´šUT2ÝŽ®Ñ8Š(›jB´ÂUT2ݰ‘8È›k:´¢T³T2ܲ‘8‘H›l*´bTT2ÛŽ´Q8•›m"´ÒTKT2XÚŽ¶8™(›n"µTËT2XÙŽ·Ñ8H›o´ÚTóT2˜Ù¹‘8¡(›p´²TóT2Ø Ø»Q8¤¨›q"´ºTãT3 ׎½8¨h›r*´’TóT3X ÖŽ¾Ñ8¬(›s´jTóT3˜ ÕŽÀ‘8¯è›t´JT»T3Ø ÕÂQ8´›u:´*T»T4XÔÄ8·è›vR´2T³T4˜ÓŽÅÑ8»ˆ›w‚´jT{T4ØÒŽÇ‘8¿h›xª´SãT5XÒÉQ8ÃH›y²³êSƒT5˜ÑÊÑ8Lj›z´S›T5ØÐŽÌ‘8Ì›{Ú´*T T6XÏŽÎQ8Ð(›|ê´ZTƒT6˜ÏÐ8Ô›~ ´ºTËT6ØÎÑÑ8ØH›*´ŠT«T7ÍŽÓ‘8܈›€:´RT£T7XÌŽÕQ8àÈ›J´jTÓT7˜ËŽ×Q8å(›‚J´2T£T7ØËÙ8é(›ƒR³ÚT[T8ÊÚ‘8íh›„гšTT8XÉŽÜ8ñ¨›…ʳZSûT8˜ÈŽÝÑ8õ蛇³BTX9Èß‘8ùÈ›ˆJ³T X9XÇáQ8þ(›‰Z²êT3X9˜ ÆŽãQ9ˆ›Šz²ºT+X9Ø!ÅŽäÑ9È›‹ª²ªSû\9Ø"Åæ‘9 蛌겲S£\:#Äè‘9h›Ž*²zS£\:X$ÃŽêQ9è›b²BS»\:X%ÂŽëÑ9h›’²*S‹`:˜&Âí‘9È›‘â²BS“`:˜'ÁïQ9!H›“2²"Ss`:˜(ÀŽñQ9%H›”z±ÚRë`:X)¿Žó9)h›•±zRcd:X*¾ŽôÑ9-¨›— ±bQãd:+¾ö‘91È›˜b±ZQ{d9Ø,½øQ96›™Ú±ŠQkd9Ø-¼Žú9:››J² QÛd9˜.»Žü9=È›œª²ŠRSd9X/»ýÑ9A¨›ê²¢R{d90ºÿ‘9E¨›Ÿ ²BR[d8Ø1¹Q9I¨› "²RRS`8˜2¸9M蛡Z²¢R[`8X3¸‘9R(›¢‚²ÊRC`84·Q9V(›£º³:R‹`7Ø5¶9ZH›¥³âS‹\7˜6µ Ñ9^ˆ›¦B´JTs\7X7µ ‘9b¨›§j´2Tó\7X8´ ‘9fˆ›¨Š´TÃ\79³9j¨›©¢³ÒT3\6Ø:²Ñ9nˆ›ªº³šSÓ\6Ø;²‘9r¨›«â³ªSƒX6˜<±Q9v¨›­"´ S›X6˜=°9zˆ›®J´ZTX6˜>°‘9~È›¯Z´zTcX6X?¯Q9‚¨›°b´ZT[X6˜@®9†h›±j´TX6˜A­Ñ9Šˆ›²r³²S³X6˜B­‘9Žè›³Š³zS‹X6ØC¬ Q9’è›´²³ÚSËX6ØD«!Ñ9–È›µÊ´ SëX7Eª#‘9šè›¶Ú³âTX7XFª%Q9Ÿ›·ú³²SÛX7˜G©'9£H›¹*³ZS#X7ØH¨(Ñ9§¨›ºb³ZR›\8I¨*Q9«è›»š³šR£\8XJ§,9¯È›¼Ê³âS\8˜K¦-Ñ9³è›½ú³úS‹\8ØL¥/‘9¸›¿:´T;\9XM¥1Q9¼H›Àr´2T‹\9˜N¤39Àˆ›Áª´RT[\9ØO£59ÄÈ›ÂÚ´ŠT \:XP¢6Ñ9Èè›Ä´‚SÃ\:˜Q¢8‘9Í(›ÅZ´:S[\;R¡:9Ѩ›Æª´"S#\;XS ;Ñ9Õè›Çú´ŠSc\;ØT =Ñ9Ú(›É:´²S«`<UŸ?‘9Þ¨›Êz´jSÓ`]™M‘:è›Õ"´’T+`>X^˜OQ:h›Öz´‚TK`>˜_—QQ: È›×Ê´RTƒ`>˜`—S:(›Ù2´"Tkd>Øa–TÑ:țڒ³ÚT+d?b•VÑ:ˆ›Ûú³²Td?c”X‘:(›Ýb³‚Sëd?Xd”ZQ:"¨›ÞÒ³bSãh?˜e“\:'(›à:³BSóh?Øf’^:+h›áª³*SÓh?Øg’_Ñ:/è›ã³S‹l@h‘a‘:4h›äš³S+l@Xic‘:9›æ²úRãl@Xje:=ˆ›ç¢³"RÓp@˜kg:B›é"³RRãp@ØlŽhÑ:Fˆ›ê’²òR³p@Ømj‘:Jè›ì²ÚR{tAnl:O›íÒ³ R£tAXoŒmÑ:SH›ïš³BS{tA˜p‹o‘:WÈ›ñ2³:SÃxAØqŠqQ:\H›òª³2SSxBrŠsQ:`ˆ›ôB³rS#xBs‰uQ:dè›õê³RRûxBXtˆw:ih›÷’³2SxB˜u‡xÑ:mÈ›ùB³:SkxBØv‡zÑ:rH›úú³SËxCw†|Q:vÈ›ü’²ÒTxCXx…~Q:{(›þ2²šTxC˜y…€:ˆ›ÿÚ²rSËxCØz„Ñ:„œ’²’SÃ|D{ƒƒÑ:ˆÈœ2²ZS£|DX|‚…Q:Hœ²S[|DX}‚‡:‘ˆœ‚±ÒRû€D˜~ˆÑ:–œR±‚Rƒ€DØ€ŠÑ:šèœ ±2R €DØ€€Œ‘:ŸÈœ ʱjQ»„DØŽ‘:¤œ ¢² QÓ„DØ‚~Q:¨Hœb²:QÈD؃}’:¬ˆœ"²"Q‹ˆDØ„}“‘:°Èœ ²QkŒDØ…|•‘:µœú²ZQ“ŒD˜†{—:¹(œê²’QÛD˜‡{™:½HœÚ²ºRKDXˆzšÑ:Á(œ²³ Rë”D‰yœ‘:Åœ‚³RSK”CØŠyž‘:Éœr³’SK˜CX‹x Q:Ìèœ r³êS˜CŒw¡Ñ:Јœ"j´rSœB˜w£‘:ÔHœ$b´òS3œBŽv¥‘:×èœ&Jµ:S«œA˜u§Q:Ûˆœ(µZSë At©:ß(œ)âµ²TK @˜‘t«:âèœ+ºµúT³ @’s­:æHœ-‚µêTˤ?˜“r®Ñ:éhœ/RµÚU¤?”q°Ñ:쨜1BµêU¤>˜•q²‘:ðHœ3*µâTë¤>–p´Q:óÈœ4úµÂTƒ¨=˜—oµÑ:÷(œ6µrSÓ¨<ؘo·Ñ:ú(œ8’µŠS«¨¶JU3¬:˜œl¿;Hœ?¶ U¬:kÁ; (œAjµ²Tk¬9˜žjÃ; ÈœC"µ¢T¬9ŸjÄÑ;hœDÚµ¢S£¬8X iÇ;HœFеrS{¬7Ø¡hÈÑ;hœH2µZS“¬7X¢hÊ‘;hœIµ’Sì6Ø£gÌQ;(œKr¶T[¬6X¤fÎQ;(œM*¶2TÛ¬5Ø¥eÐ;ÈœNµÊTÓ¬5X¦eÒ;"HœPRµŠTs¬4اdÓ‘;$èœQÚµŠTS¬4X¨cÕQ;'hœSRµŠTS¬3Ø©c×Q;*HœTʵbTc¬3XªbÙ;-œVjµrT³¬2˜«aÛ;0œWòµŠTã¬2¬aÜ‘;3(œYRµrTã¬1˜­`Þ‘;5ÈœZµbTó¬0Ø®_à‘;7èœ\Jµ2Tã¬0X¯_â‘;9èœ]Ê´êT{¬/˜°^ä‘;<(œ_J´ÒT#¬.ر]æQ;>ˆœ`º´âT ¬.X²\è;A(œb´òSÓ¬-˜³\éÑ;CˆœcZµS£¬,Ø´[ë‘;Eˆœd²´úS[¬,µZí‘;GÈœeò´ÚS#¬+X¶ZïQ;Jœg:´ÊS+¬*˜·Yñ;L(œhŠ´êSk¨)ظXó;Nhœiµ"S˨)¹Xõ;P¨œjúµrSû¨(˜ºWöÑ;Rèœl"µšSã¤'Ø»Vø‘;T¨œmBµšS›¤'X¼Vú‘;VˆœnZµÚS« &ؽUü‘;X¨œo‚¶T &X¾TþQ;Zèœpª¶ T³œ%Ø¿TQ;](œqºµúUK˜%ÀS;_HœrºµšUK˜$˜ÁRQ;aˆœsʵ"Tû”$ÂQQ;cˆœtʵTÓ#˜ÃQ;eˆœu²µ"TËŒ#ÄP Ñ;gÈœvšµTSŒ"˜ÅO ‘;jœw‚´ÂS{ˆ"ÆO Q;lœxz´úS„!˜ÇN;mèœyR´êRÀ!ÈM;p(œz µSC| ØÉMÑ;rˆœzʵrTx ˜ÊL‘;t¨œ{¢µzT“x XËLQ;v¨œ|Rµ*Tct ÌKQ;x¨œ} µ2T#tØÍJQ;zˆœ}º´òS£pØÎIÑ;}œ~R´²SSpØÏI‘;Èœ~ò´’SSpØÐH‘;蜲´rS«p ÑH!Q;ƒÈœ€Z´ZT p XÒG#;…蜀ú´:Sët ˜ÓF$Ñ;ˆhœÊ´S+t ˜ÔF&‘;Ѝœ‚š´zR³x ØÕE(Q;Œ¨œƒr´òRÃx!ÖD*Q;ŽÈœ„jµS|!X×D,;蜅Zµ:S›€!˜ØC.;“(œ†*µrT€!ØÙB0;•hœ†úµZT[„"ÚB1Ñ;—蜇ú´òT;„"ÛA3‘;šHœˆê´ÒSóˆ"XÜ@5;œHœ‰Úµ Sãˆ"XÝ@6Ñ;žHœŠÚµRTSŒ"XÞ?8Ñ; (œ‹ÚµZTËŒ"Xß?:‘;¢hœŒ²µ"T›Œ"Xà>åÑ<Áèœßj³šTT%™?ç‘<ÄÈœà"³šT3T%Y@é‘<LjœàʳšTST$ÙAëQ<Êhœá‚³‚T‹T$™Bí<ÍHœâB³BTƒT$YCîÑ<Мâú²ÚT#T#ÙDðÑ<Ò¨œã²bS³T#™Eó<ÕHœäбòS+T#YFõQ<×èœåB±ÊR³T"ÙGÿ÷<Ú¨œåò±²RkX"™HÿøÑ<Ýhœæ’±‚R3X"Iþú‘<ߨœçB±šRX!ÙJþü‘<áÈœçò±¢R;X!™Kýþ‘<äHœèª±ZRKX!Lü‘‘<æèœéZ± R;X ÙMü<éhœê °òR3X YNû‘<ëèœêº°òRCX Oû<îHœëb°ÂRCXÙPú‘<ðhœëò°šR\YQù‘ <ò¨œìš°jQû\Rù <õœíJ°"QÛ\ÙSø‘<÷hœíú¯úQ³\YTøÑ<ù¨œîš¯âQÃ\U÷‘Ñ<ûèœï2¯ÂQÛ\ÙVö‘‘<ýèœïÒ¯ªQ³\™Wö‘<ÿèœðj¯jQ£\Xõ‘Q=(œñ ¯BQk\ÙYõ‘=(œñ²¯jQc\™Zô‘=(œòJ¯ZQ[\YZ ôQ=(œòJ¯:QK\Y[ó‘Q=(œòÚ¯Q;\\ó= Hœór®úQ#XÙ]ò‘!Q= Hœô¯Q3X™^ò#=hœôš®ºQ TY_ñ‘%Q=HœõB®šPóP`ð‘'=(œõâ®úQLÙað(Ñ=œöb®úQ HÙbï‘*‘=œöꮂP³D™cï,‘=œ÷Z®JPc<™dî‘.‘=œ÷º®ªPc8™eî0‘=Hœø®ÒP30Ùfí2Q=ˆœøz®²P ,gì‘4Q= èœøÚ®šP#(hì6Q=#œù"®êPK ™ië‘8=%Hœùr¯2PƒÙjë9Ñ='¨œùº¯P£kê‘;‘=*œùê¯PóYlê=‘=,¨œú2¯Q#Ùmé?‘=/ˆœúŠ®ÒQKnè‘A‘=2(œúÊ®ªQKYoèC=4¨œû®‚QÙpç‘DÑ=7(œûZ®ZPãqçF‘=9Èœûš®P“Yræ‘H‘=H «jMÛ@ Y²Ä‘¼‘>¨ «¢MÓ@™³Ä¾‘>ˆ!j«ÂM»@Y´ÑÀ‘>È!ò¬Mã<ٵÑ> "j¬BN#<Y¶‘ÄQ> h"ʬzNS8Ù·ÂÆ>#*¬ªN£8™¸Á‘ÇÑ>¨#š¬ÊNÛ4Y¹À‘ÉÑ>è$"¬êO4ºÀ‘ËQ>è$’¬ÚO4Ù»ÀÍ>H$ò¬ÊO0™¼¿‘ÎÑ>è%Z­2OS0Y½¿ÐÑ>ˆ%­²O£,¾¾Ò‘>è&*­’O»,Ù¿½‘Ô‘>!(&’­ROÛ,™À½‘ÖQ>#h&â¬úOÓ(YÁ½Ø>%È'2¬ºO{(Y¼‘Ù‘>(('’¬bO$üۑ>*H'ú¬*N›$ÙÄ»‘ÝQ>,h(b¬N; ÙÅ»ß>.ˆ(º¬ N ™Æº‘á>0¨) ¬2NK™ÇºâÑ>2È)Z¬rN³™È¹‘ä‘>5H)š¬‚O ™É¸‘æ‘>7¨)â¬RO™Ê¸è‘>9ˆ*B«úN˙˷‘êQ>;È*z«ºN{ÙÌ·ì>>*’«’N+Ͷ‘íÑ>@H*Ò«¢N+YζïÑ>BÈ+¬Ns™Ïµ‘ñ‘>Eˆ+b¬NcÙеó‘>GÈ+º¬NsYÑ´‘õQ>J, «¢NC™Ò´÷>Lˆ,B«zNÙÓ´øÑ>Nè,š«²N3YÔ³‘ú‘>Q¨,ò«šNK™Õ³üQ>Th-B«jNƒÙÖ²‘þ>VÈ-ª«2N»×²>YH.ªÊNsYر>[È.bª’MûÙÙ°’>^H.ªÊMãÚ°>`è/:«*N+YÛ¯’Ñ>c¨/š«RN{™Ü¯’ Q>fh0«RN«Ùݯ >i(0‚«:Nà ޮ’ >kÈ0âªòN³ ™ß­’>n¨1Bª’Nk Ùà­Q>qˆ1ºªBMû!ᬒQ>t(2Jª*M“!Yâ¬>vè2ªªBMƒ!™ã«’Ñ>z2ÚªZM‹!Ùä«‘>}3"ªjMƒ"媒Q>è3‚ªRM{ "YæªQ>‚È3êª*Mc"™ç©’Q>…è4J©êM;"Ùè© Q>‰H4Š©jLÛ#騒"Q>Œh4ª¨úLrü#Yê¨$>ˆ4â¨âL*ø#Yë§’&>’ˆ5B© Lô#™ì§(>•ˆ5š©2Lô#Ùí¦’*>˜¨5Ê©JL2ð$î¦,>›è5ò©BLbì$Y勒.>ŸH5Ú© Ljè$™ð¥/Ñ>¢ˆ5ʨúLjè$Ùñ¤’1‘>¥è5Ú©2Ljè$Ùò¤3Q>©h6¨òLRä%ó£’5>­6"¨¢Kêä%ô£7>°h62¨zKbä%õ¢’8Ñ>³è62¨rJòä%ö¢:‘>·H6:¨jJºä$Ù÷¡’<‘>º¨6R¨šK è$Ùø¡>Q>½È6š©K‚è$™ù ’@Q>À¨6Ú©zLì$Yú BQ>ÃÈ6ê©ZLzì$YûŸ’D>Æè7¨òLªð$üŸ’E‘>Ê(7J¨ªLâô#ÙýŸGQ>͈7‚¨rMø#Ùþž’IQ>Ðè7²¨bMø#™ÿžKQ>Ô7ò¨BLúü#š’MQ>ÖÈ8:¨Lã#ZO>ÙÈ8z§²L«#Zœ’Q>Ý8§RLk#œS>àh9§L##›UQ>ã¨9j¦ÊKÓ #š’WQ>æˆ9ʦŠKk"ÚšY>éH:B¦’Kc"š™’[>ì(:š¦ÚK‹"š™]>ï(:ò¦²Kc"Z ˜’_>ñè;r¦rKc " ˜’`Ñ>õ(;ê¦:K{ !š ˜b‘>øHû<Ú¦ZKS(! —fQ>ýˆ=R¦JÛ, Ú–’hQ?h=Ê¥ÒJ«0 Z–j?>Z¦ J{0 •’l?H>ò¦ZJ34Ú•mÑ?¨?b¦RJ8Ú”’o‘? ¨?º¦ZJ+<š”q‘? (@:¦zJ+@š“’s‘?(@Ò¦¢JKDš“u‘?hAR§JkDš’’wQ?èAÚ§bJcHÚ’yQ?(Bb§’JkL ‘’{Q?ˆC¨RJëP Z‘}Q?HC²©2KÃT š’Q?Dr©LCT Ú€Ñ? hE:¨ÊL“X!’‚Ñ?"ˆF¨jL{X!Z„‘?%(F²¨*L3\!ZŽ’†Q?'ÈGr¨JL+\!šŽˆQ?*HHB¨ZL3\!š ŽŠ?,ÈI¨bLs`!Z!ŒQ?/(I²¨JL“`!Z"Ž?1ˆJb¨:LS`!#Œ’Q?4(K2¨:L\ Ú$Œ’?6èKê¨*L\ š%‹’“Ñ?9(L²¨2L#\ Z&‹•‘?;(Mr¨"KûXÚ'Š’—‘?=HN¨ KÃXš(Š™Q??ˆNª¨:KÓT)‰’›?AèOJ¨BKËPÚ*‰œÑ?DHOâ¨JKëLZ+ˆ’žÑ?FÈPr¨ŠL#HÚ,ˆ Ñ?HèPò¨‚L+Dš-‡’¢Ñ?K(Q’¨bL @.‡¤Ñ?MÈR¨:KË8š/†’¦Ñ?P(Rš¨:K£4Z0†¨‘?RˆS¨rK{,1†ªQ?T¨SR¨bKK(š2…’¬Q?VèSª¨rKc Z3…®Q?YSê¨zKs4„’°?[hT*¨JKK5„±Ñ?]ÈTz¨bK[Ú6ƒ’³Ñ?`Tª¨²K«š7ƒµÑ?bTʨÊKû š8‚’·Ñ?dHTò©*Lc Z9‚¹Ñ?gU"©ZL›Z:’»Q?ihUJ©jM#Z;½Q?kÈUz©jMc <€’¿Q?nU©zM =€’Á?p(V ©zLƒÚ>€ÂÑ?rHVR©zKÛÚ?’ÄÑ?t¨Vš©šKCš@ÆÑ?vèV⩺K šA~’È‘?y(W2ªKKZB~ÊQ?{(WŠªšK»ZC}’ÌQ?}HWꪂL[ D}Î?ˆX*ªbLë$E|’Ð?ˆXrªM+$F|’ÑÑ?ƒˆX©ÊM (G|ÓÑ?…ˆYB©ªLû(H{’Õ‘?‡ˆYª©šLó,I{ב?‰ˆZ©zLë,ZJz’ÙQ?‹¨Zz©RL£,ZKzÛ?ÈZÚ©BLK0šLy’ÜÑ?è["©L0ÚMyÞÑ?‘è[‚¨êL+0Nyà‘?”[ú¨ÊL[4Ox’â‘?•è\j©L“4ZPxäQ?—è\Ú©*LÓ4šQw’æQ?šˆ]*¨âLó8ÚRwèQ?]z¨šM8ÚSv’ê?žè]ò¨RLû<ÚTvì?¡(^r§êL‹<ÚUu’íÑ?£h^â§’L@ÚVu’ï‘?¥ˆ_:§ZK‹@ÚWuñQ?§È_²§:KƒDÚXt’ó?ª`R§rK«HšYtõ?¬`â§ŠKÃLZZs’÷Q?®(aj§ŠLLÚ[sùQ?°Haò§*K»PZ\r’ûQ?²Hbz¦²KTÚ]rýQ?´Hc¦ªJ›TZ^q’ÿ?¶cª§2JƒTš_q?·Èd*§2JKX`q‘?¹(dЦêIÛXZap“Q?º¨e¦êI»XšbpQ?¼ˆez§I³Xšco“?¾Heê§bIëTÚdo ?¿ˆfZ§zJ;Ten“ Q?Àèfº§JJ[PZfn?Âg§RJCLšgm“Ñ?ÃHgB§JJ3Hhm“Ñ?ÄÈgz§:JsDZimÑ?Åèg§RJ«<Újl“Ñ?ƨh§²JË8ZklÑ?ÇÈhZ§âJã0Úlk“‘?É(hЧÂK (šmkQ?ÊHhº§ŠK+ Znj“Q?Ëhhò§¢KSoj‘?ÌÈi§òK«pi“!‘?Íèi"§ÂK£ Úqi“#Q?ÎÈi:§rK{ Úri%Q?Ð(iZ§‚KŠø Úsh“'?Ѩir§zKªð Úth)?Òˆi‚§JKÂèug“+Q?ÓˆiЧKšàvg-Q?Õiš¦ÊK‚ØZwf“/?Ö¨iЦ‚KZКxf0Ñ?×Èiz¦BK*ÈÚyf2Ñ?ÙHiz¦ KÀze“4‘?Úˆi’¦:Jâ¼Z{e6Ñ?Û¨i’¦ŠJò´Ú|d“8Ñ?Ýir¦ŠJâ°Z}d:Ñ?ÞˆiJ¦BJ‚¨Ú~c“<Ñ?ßèi"¥êJj¤Zc>Ñ?áHi¥šJ: €b“@Ñ?âÈhÒ¥RIz šbBÑ?äHh¢¥ZH‚œZ‚bDÑ?åèhr¥úG꜃a“G?çÈh2§*H*œš„aIQ?êgú¨šIZœZ…`“K?ìgÊ©:J‚ †`M?íÈg²©2Kz š‡_“O?ïègŠ©"LB¤ˆ_QQ?ò(gR© Lò¤Ú‰^“SQ?ôhg"¨êMB¨ZŠ^UQ?ö¨fú¨ÒM¨ÚŠ ^UÑ?ö¨fú¨ÂM¨Ú‹]“WQ?ùfʨšM¬ZŒ]YQ?ûfš¨bMR¬][Q?ýHfr¨M °šŽ\“]?ÿ¨fJ§ÒLj´\_Q@(f:§ZK‚´š[“a‘@¨f¦âJ‚¸‘[cQ@(f¦²IÚ¼š’Z“eQ@ Èeò¦âI⼓ZgQ@ (eâ§BJ:Àš”Y“i‘@ÈeÒ§jJªÀ•Yk‘@ÈeʧBJúÄš–Ym‘@èe²¦òJÒÄ—X“o‘@Èe’¦šJBÈZ˜Xq‘@ˆe’¦¢IúÌš™W“sQ@He¢¦òJ"Ì šWuQ@ Heš§*J‚Ì Z›V“wQ@#he’§bJúÐ ZœV“y@&ˆeЧzK:Ð ZV{@)¨eЧ‚KÂÔ ZžU“}Q@,ˆe¢§BKêÔ ZŸUQ@/ˆe²§KbÔ  T“@2ˆeº¦ªJ¢ÔÚ¡TƒQ@5he¦zJ Øš¢T…@8HeʧIjØZ£S“‡@;(eò§šIØÚ¤SˆÑ@=èf§šHêØZ¥R“ŠÑ@@ˆf*§ºHúÜÚ¦RQ@CHf2¨jIZÜZ§Q“Q@Eèf*¨âI²ÜÚ¨Q‘@HHf*¨ÒIúàZ©Q’Ñ@J¨f*©bJŠàÚªP“”Ñ@MHfBªZKJäZ«P–‘@OhfbªŠKŠä¬O“˜‘@Q¨frª*KšèÚ­Oš‘@Sèfrª K²ìš®Oœ‘@VHf‚ªJL ðZ¯N“ž‘@Xhf¢ªjLZðZ°N ‘@ZÈfêª*Lšô±M“¢‘@]Hg"©âMRø²M¤Q@_¨gR©ªN ü³M¦Q@aÈgr©rMë´L“¨Q@dgš©*M+ÚµLªQ@fhgÚ¨ÚLKÚ¶K“¬@h¨h"¨¢Kk Ú·K®@jÈhr¨âJÛ š¸K°@mhÊ©JJÓZ¹J“²@o(i©¢KºJ´Q@q¨i:©¢K3Ú»I“¶Q@tiŠ©bKš¼I¸Q@viê©"Jã½H“º@xj:©RJÛÚ¾H“»Ñ@yÈj’©ÒK Z¿H½‘@{ÈjâªKsÀG“¿Q@}Èk©ÚK{šÁGÁ‘@¨kZ©bK3ZÂF“Ñ@¨kš©*JëÃF“Å‘@ƒhkê©jJëšÄFÇQ@…l*©ÊJûZÅE“É@†ÈlR©êJÓ ÆEË@ˆ¨l‚©ªJ“ ÚÇEÌÑ@Šhlº©’J›ÚÈD“Α@Œ(lêªJãšÉDÐQ@Ž(m ªrK+šÊC“ÒQ@Èmª:KRüšËC“Ô@‘Hm*ª:KjøšÌCÖQ@“hmRªJKzôZÍB“ØQ@•ˆmzªJKªðZÎBÚ‘@—hmŠª‚KúìZÏA“ÜQ@™(mšªÊKòèZÐA“Þ@šÈm²ªŠKšäZÑAßÑ@œˆmÒªzKŠàZÒ@“â@žhmòªjK¢àZÓ@ãÑ@ hmêªZKšÜZÔ@åQ@¢(mêªzKrØÕ?“çQ@£èmâªjKJØÖ?éQ@¥hmâªBJòÔ×>“ë@§(múªÚKÔØ>“ìÑ@¨èmò«ªK’ÔÙ>îÑ@ªÈmʬKâÔÚ=“ð‘@¬Èmº«òKâÔÛ=ò‘@®èm«¢L ÔÜ=ô‘@°¨m⫪L*ÔZÝ<“öQ@²Hn«ÂLZÔZÞ<øQ@´Hn«âLòÔZß<ú@¶n«òMRÔšà;“ûÑ@·¨mò«ÊM2Ôšá;ý‘@¹Hn«²M ÔÚâ:“ÿ‘@»Hn«²LêÔÚã:”Q@½(n«¢LÊÔä:@¾Èn*«JLjÔå9”Ñ@ÀˆnB«‚LZÔæ9”‘@ˆnR¬"LºÔZç9‘@ÄÈn:¬bMØZè8” ‘@Çn2¬"MØZé8 Q@Èèn:«ÚMØZê8@ÊÈnB«‚LêÜë7”@ÌÈn2«"LŠÜì7Ñ@Îèn2«*LjàÚí6”Ñ@ÐÈn:«zL:äšî6”‘@ÒÈn:«JKªèZï6‘@ÔˆnR« Kìð5”Q@ÖHnr«*JÚôÚñ5”@×ÈnŠ«rJâøZò5@ÙHnº«zKüó4”Ñ@Û(nê«‚K£Úô4!@Üèo «’LKšõ4"Ñ@ÞˆoB«’Lƒ ö3”$‘@ßèoš¬ L‹ Ú÷3&‘@á(oú¬jL³šø3(Q@â¨p¬zM Zù2”*@ä(p2¬ZLÛ Úú2,@å¨pr¬L‹ šû1”.@ç(pª¬LcZü1”/Ñ@èhpÚ¬ZLCý11‘@éèq¬¢LBøÚþ0”3‘@ë¨q¬òLbôÚÿ05‘@ípê­2L¢ìÛ07‘@î(pú­’LÊäÛ/”9Q@ïhq*® M"ÜÛ/;Q@ðˆqB®2MbÔ/=Q@ñ¨q®BMrÐ[.”?@ópê®ZMbÌÛ.A@ôHpâ®"M"È.BÑ@õèpÒ­ÊLâÈ›-”DÑ@÷hpÒ­âL²È-FÑ@ù(pÊ®‚LºÈ› ,”HQ@û(p²®âMÈ ,”IÑ@üèpНM‚Ì› ,K‘@þèpb®¢MÐ +”M‘Aèp‚®ªLÚÔ[ +”OÑAÈp¢¯ZM:ØÛ+QÑA¨pš°MÒÜ*”S‘AÈpª°JNà[*”U‘AÈpʰNšà[*W‘A hpâ¯êOZä[)”YQA (q ¯ºO’è)[QAhq:¯ŠO’èÛ)]QAèqZ¯ROZè›(”_QA(qZ¯:NŠè(aQA(qj¯ÊMúè['”cQA¨qª°’MÚè›'”eAÈqâ°rMºèÛ'gAqê°2MÊäÛ&”iAèqò°2Nà&”kAˆr°šNRÜ&mAˆr*°êNŠÔ[%”oAˆr± NŠÌ [%”p‘Aˆr°òNZÄ ›%rQA Èqò°âNR¼  $”tA!èqÒ±JN¢´ [!$”vA"Èq²±JN²¨ "$xA#hq²°úN‚  ›##”zQA$(q¢±JNª˜ ›$#|A$¨qz±’NÚ [%#}ÑA%hq:±bNªˆ [&"”ÑA&(q±*Nj„ ['"‘A&Èq ±ÒNÊ€ ›("ƒ‘A'¨pú²zO:€ Û)!”…ÑA(ˆpÚ²jOŠ| *!‡‘A)¨p¢²"O¢| ›+!‰‘A*ÈpZ±êOš| Û, ”‹‘A+¨p*±²Ošx [- ‘A,¨p*±²Oºx Û.”‘A-¨p²Oúx /”‘‘A/oÒ±êPx ›0“‘A0ho‚±šP x1”•QA1¨oJ±ROâx›2”—QA2Èo±*OÂx3™‘A3Ènê±BO‚t›4”›‘A5HnÒ±*ORtÛ5”QA6Èn’±O²t6ŸQA8hn2°òOòt[7”¡QA:(mò°ÂOªt[8£QA;¨m°šOrt[9¥A=m‚°ÊOBt[:”¦ÑA>ˆm"°òNêt;”¨‘A?ÈlÒ°úNŠt<ª‘A@èlª±N¢xÛ=”¬‘AB(lj±*Nâx›>”®‘ACHlJ±NÂ|›?°QADhl:±NÂ|›@”²‘AEˆl±*Nª€›A´QAFˆkÒ±*N‚€ÛB¶‘AGÈk’± N2„C”¸‘AIhkr±RN"„›Dº‘AJèkB±¢NªˆÛE¼QALhk±ºNòˆ[F”½ÑAMèjò±ÊO2ŒÛGÀAOhjÒ±ªORŒ[HÂAPèjz±ŠOšŒÛI”ÃÑAR¨j2±rOÂŒ[J”Å‘AT¨j±jOâÛKÇ‘AVHiò±²P"L”ÉQAWèi²±’Oú›M”ËQAY¨i‚±ROÒÛNÍQA[¨iR±OªO”Ï‘A]Èi°ÂOB[PÑQA_èhº°ŠO›QÒÑAa¨hz°ŠNú›R”Ô‘AchhZ°ºNÚ”ÛS”ÖQAe(h*°ÒNÊ”TØ‘Aggê°ŠNÊ”U”Ú‘Ai(gº°2NÒ”[V”Ü‘Ak(gz°Nʘ[WÞAlèg:¯âN²˜›X”àAn¨g"¯ÂN²œ›Y”áÑApHg¯¢N²œ›ZãÑArHfâ¯jN¢œ›[åÑAtˆfš¯*N² ›\”ç‘AvÈfb®êN¢ ›]éQAxèf:®ÊNj¤›^êÑAzÈf ®¢N"¨[_”íA|¨eò®bM¢¨`ïA~¨eò®bMB¬ÛaðÑAeÒ®rMR¬›b”ò‘Aƒeš®‚MB°[c”ôQA„Èe‚®rLâ´dõÑA†ˆeb®‚L¸›e÷‘AˆeB®²Lʼ[f ”ùQA‰Èe"®ÊL’Àg ûA‹ˆe"®òLŠÄÛh ýQAHe¯:LâÈ›i ”ÿA(e ¯jM2Ì[j ÑAèe¯zM:Ð[k A’ˆe*¯‚M‚Ô[l •ÑA”e2¯‚MúÔm •QA•ˆe2¯rNØn A—(eB¯ZNÜo • A™(eR¯jMòà[p • ÑA›(eR¯zN:ä[q  ‘AœÈeZ¯JN2è[r ‘Ažhe‚¯Nì[s •AŸèeš®òN"ì[t ÑA¡¨e¢®ÊNRðu ÑA£¨e®ŠN2ôv•QA¥ˆeâ®bMúøÛw•A§ˆf®ZMºø[xÑA©Hf®JM‚üy‘A«(fR®:M#›z•‘A¬Èf’®’M{A®Hf²®òM[|!A¯Èf®âLãÛ}•"ÑA±(fú®¢L« ~•$QA²g2®ÊL«[&A²ègR¯"Ló ›€•(QA³ègz¯zM Û•*Aµg²¯jM3 ‚+ÑAµègâ¯ZMC ƒ-‘A¶Èh¯rMK [„•/ÑA·Èh*¯rMK Û…1ÑA¸¨hJ¯ÚM› †3QA¹hhZ°"N [‡•5A¹èhR°*N+Ûˆ•7Aºhhj¯ÂN3‰8ÑAºèh‚¯’N"ô›Š•:ÑA»ˆhz¯šMÒì‹•<‘A¼(hr¯‚MbàÛŒ>‘A¼¨h‚¯ºMZÔ[@QA½h‚°MŠÄŽ•BQA½(hb¯úM’´ÛDQA½hhr°BMÒ¤ÛFQA½Èh‚°‚NJ”Û‘•HA¾(hj°BN2„Û’•I‘A¾hhR°*N tÛ“K‘A¾ÈhB°Mâh”ÿ•MÑA¿h2° M²`[•ÿ•OÑA¿ˆh°ZM‚X›–ÿQQA¿ègò°ZMŠPÛ—ÿSAÀHgê°RMâL[˜þ•UAÀ¨gʰRNL›™þWAÁ(g’°JNbLšþYAÁ¨gj°2NŠL››ý•[AÂhgB°NjPÛœý]QAÂèg¯ÊNJT[ý_‘AÃhfº¯¢MÒ\Ûžü•aQAÄf‚¯ŠMš` [Ÿü•bÑAÄèfb¯ªM¢h › üeAÅèf*¯ªMRp Û¡û•gAÆèeꯚM²x [¢û•hÑAÇÈeÒ¯ŠMÚ€ ›£ûj‘AÈÈeº¯jMÂŒ Û¤ûlQAÉèe’¯RMâ” ¥ú•nQAÊÈe‚¯ZM’œ ¦ú•pQAËÈeН’Mr¤ [§ úrAÌèej¯ºMÒ° [§úrAÌèej¯ÂMÚ° [¨ù•tAͨeB¯ÊMÒ¸ [©ù•uÑAΈe:¯ÂMºÀ [ªùw‘Aψe2¯ªM²È «ùyÑAШe2¯ªMzÔ ¬ø•|AÒe:¯²MrÜ Û­ø~QAÓ(eR¯²M²ä ›®ø€QAÓèeZ¯¢M‚ì [¯÷•ÑAÔÈeZ¯ŠM‚ô Û°÷„AÕ¨er¯‚M²ü ›±÷†AÖÈe¯ÂM³ ²ö•‡ÑAØeÚ¯ÒMÓ Û³ö•‰QAØèeÚ¯ÒN[´ö‹AÙeꯊM»ÛµöAÙHf¯‚M{ [¶õ•AÙèf2¯ÊMk$Û·õ‘AÚˆf:°M‹([¸õ’ÑAÛfR°"MÃ,Û¹ô•”ÑAÛˆf‚°rMã([ºô•—AÛèfš°ÂN3$Û»ô˜ÑAÜHfº°úNk[¼ôš‘AܨfÚ±:N‹ Û½ó•AÜÈfê°úNrð[¾óŸAÝfÚ°ªNjÌ¿ó ‘AÝHfÚ°ÊNb˜ÛÀò•¢ÑA݈fâ±*N‚`ÛÁò¥AÝÈf±*N’(Âò¦ÑAÞ(f’±N¡ü[Ãñ•¨ÑAÞHf‚±BNÉØÛÄñ•ªÑAÞ(fr±BNÙÀ[Åñ¬ÑAÞHfJ± NÙ°Æñ®‘AÞhf±NѤÛÇð•°ÑAÞˆeâ±BNÙœ[Èð³AÞ¨e¢±*N¹”Éð´ÑAÞÈeB±N¹›Êï•¶ÑAÞ¨dò±2NÉŒËï¸ÑAÞ¨d±ŠN¹Œ›Ìï»AÞÈdj±JN©ˆ [ÍAßcú±*N™ˆ ÛÎ‘AßHcª±šNÁ„ ÏîÀ‘AߨcZ±ÚNé„ ›Ðî‘Aߨb걚NÉ„ Ñí•Ä‘A߈br±ÒNñˆ ›ÒíÆ‘Aߨb±ÚOˆ ÓíÈ‘Aàaª±ŠOˆ [Ôì•Ê‘Aà(a*±JO1Œ ÛÕì•ÌQAà(`š±O9 [ÖìÎQAàh`°ºO” Û×ìБAà¨_’°’NÑ”Øë•Ò‘Aà¨_°êN™˜›ÙëÔQAá^š±NQ ÚëÖQAáˆ^"°êN!¤[Ûê•ØQAáè]’°ÂNa¨ÛÜê•ÚAâ(\ò°šN¡¬ÝêÜAâh\b°šNù°[ÞêÞAâè[Ú±O!´›ßé•ßÑAã¨["°úNù¸›àéâAähZZ°ÂO ¼ÛáéäQAå(YʰrNÙÀÛâè•æAå¨Yb°BN‰ÀÛãè•çÑAæ(XÚ° N‘ÄäèéÑAæÈXJ¯úN9Äåèë‘AçÈW¯êMÙÈæç•íAèhW:¯âM¡È[çç•îÑAèÈV²¯âMÌ[èçðÑAé(V*¯âLÁÌ›éçòÑAéÈUš°*L™ÐÛêæ•ô‘AêˆTò°ŠL©Ðëæ•öQAëHT*°¢LÑÔ[ìæøQAëèS’°ºM™Ô›íå•úQAì¨S*°ÒN)ØÛîå•üQAíˆR’°âNqØ[ïåþQAîhQê°úNÁÜ›ðåQAïHQJ±*NùÜÛñä–AðˆPª±ZNÉàòä–AñÈOê±rNÑà[óäÑAò¨O2±šNáä›ôä‘AóhNš±ŠN©ä›õã– ‘Aô(MÚ±RNiè›öã– ‘Aõ(M ±*N1ì›÷ã QAöHLZ± N!ð›øãA÷hKÚ±N1ð[ùâ–AøˆKR± Nôúâ–ÑAùˆJš±OøÛûâQAú¨Iú±Oü›üâQAûÈI‚°úNÒýá–‘AýHò°òNºÛþáQAþ(HZ± Nz[ÿáAÿ(GÒ±N"á‘AÿÈGb°úMÒ Üà–QBÈFâ°ÒN"œà!ÑBFr°ºN"œà$B(F:°ÚN œß–%‘B(Eú°úMúœß–'BèE‚±zMÂÜß(ÑBèDú±ÂMšß*ÑB(D‚²*Mr\Þ–,ÑBˆD²šMœ Þ–.‘B ÈCz²òNÚÜ Þ0‘B Bú²úOj\ Þ2‘B hBвâOj\ Ý–4QB ˆAú³O œ Ý–5ÑBÈAJ³BN œÝ8BH@¢³:NÚ œÝ9ÑBÈ@³jNú \Ü–;ÑB(?’³²O:$Ü–=ÑB(?³úOB$œÜ?‘B(>´OR(\ÜAQBˆ>j´jOb(ÜÛ–CBÈ=ê´úOZ,Û–EQB(=bµ*Oª,œÛGQBH= µ2P*,ÜÛIQBˆ<ÒµBPº,\Ú–KQBˆÐ––B.è,ú¸R©¨œ?Ж˜QB/H,Z·êRi¤@КB/¨+Ê·ÊR)¤œAЛ‘B0+*¸2R9¤ÜBÐQB0(*r¸rR9¤\CÏ–ŸÑB0h)Ò¸"RY¤ÜDÏ¡ÑB0è)B¸2RY¤\EÏ£‘B1h(‚¸‚R1¨ÜFÏ¥QB1¨'º¸jR ¬\GΖ§ÑB2'¸RQɰœHΩÑB2¨&R¸ŠQÁ´IάB3H%‚¸âQÙ¸œJÍ–®B4$²¹:Qé¼KÍ–¯ÑB4¨$¹jR9À\LͲQB5ˆ#B¹rRéÈœMÍ´‘B6ˆ"j¹ŠS1ÌNÌ–¶‘B7ˆ!йŠS9Ð\OÌ–¸QB8È Ú¹ZSYÔ\P̺QB9È "¹"SqØœQ̼B:èR¸úS1ÜœRË–½ÑB;Èš¸ÒRùàœSË–ÀB<È⸪RáàœTËÂB>(¸ÂR¹ä\UËÄB?ˆ*¸ÚRùè\VÊ–ÆQB@Èr¸ºS1èÜWÊ–È‘BAÈʸ²RñìœXÊÊ‘BC¸âRÁìYÊÌ‘BD(Z¸ÊR©ìÜZÉ–ÍÑBEh¸²Rð\[É–Ï‘BFh2¸ÚR¡ðœ\ÉÑÑBGH‚¸êRñð]ÉÓÑBHÚ¸šRùðœ^È–ÖBHèZ¸ZRÑôÜ_È–ØBJò¸RRñô\`ÈÙ‘BK(b¸rS9ôœaÈÛ‘BL(²¸ÊS!ôbÈÝQBLè*¸ÚRùô\cÇ–ßBMˆ²¸¢SøœdÇ–áQBNHJ¸RRñøeÇãQBO(â¸R©ø\fÇåQBP(‚·ÒRqü œgÆ–çBPè·²Raü hÆ–éBQhª·¢R2 \iÆëBQèb·ŠR œjÆìÑBRh*·‚R kÅ–î‘BSâ·²RB \lÅ–ð‘BS¨z·²RB ÜmÅò‘BTHB·ZR  \nÅôQBTÈ"·*QòœoÅöQBUHê·"QòpÄ–ø‘BU袷R œqÄ–úQBVˆz·QÚ rÄüBVèr·2QZ œsÄþBWHZ·bQ"tÖÿÑBW¨:·ºQBÜuבBXH2·úQZœvÃQBXÈ"¸’Q‚\wÑBXèê¸êQÉôx—QBXè¸ÂQÁèy—ÑBY²¸ÊQÁØz— BY(¢¹2RAÌ{ ÑBY(Z¹JR‰À\|‘BYH"¹BRy¸œ}Á—‘BYh¹BRq°~Á—QBY¨ â¹jRÙ¬\ÁBYè ¢¹’S)¨Ü€ÁBZ( R¹¢S)¨\À—BZH "¹ÂSQ¨Ü‚À—QBZH Ú¹ÊSI¨\ƒÀBZH ‚¹ŠS¨Ü„À‘BZˆ :¹JRé¨ …ÀQB[ ò¹BRé¬ œ†¿—!‘B[ˆ ‚¹BSa¬ ܇¿—#‘B[È ú¹BS‰¬ \ˆ¿%‘B\ š¹:S1° \‰¿'‘B\H J¹BRù´ œŠ¾—)QB\ˆ â¹ZS!´ Ü‹¾—+QB\è b¹zS!¸ ÜŒ¾-QB](ú¹rS ¼ ܾ/B]hº¹ZS¼ ÜŽ¾0ÑB]Èb¹BSÀ ܽ—2‘B^(ú¹*R‰À ܽ—4‘B^Ȫ¹"RQÀ Ü‘½6‘B_ˆb¹BR‘À Ü’½8‘B`Hò¹ZSÀ œ“¼—:‘B`ÈйJRáÀ œ”¼—Baò¹êRɸ œ–¼@Ba(‚ºS9¸ œ—¼BBah¹òSQ´ ܘ»—CÑBa躹ÊS!° Ü™»—EÑBb(rº2SQ¬ š»G‘BbHºrS™¬ \›»IÑBbH²ºBS±¨ œœº—K‘Bb¨Z¹òS±¨ ܺ—M‘Bc(â¹ÚS¨ žº—OBchRºSQ¨ \ŸºPÑBc¨Òº"Si¨ Ü ºRÑBcèйòS©¨ ¡¹—TÑBd(*¹ºS¹¨ œ¢¹—WBdHš¹²Sq¬£¹Y‘Bd¨œÿ⹚SQ¬\¤¹[‘BehœÿZ¹‚S‰°Ü¥¸—]QBeèœþê¹bSÁ°¦¸—_QBfœþr¹:S´œ§¸a‘BfHœýÚ¹ SA´ܨ¸cÑBfèœýJ¹SA¸\©¸eQBgˆœü¹Sy¼œª·—gBhœü¹SÙ¼«·—i‘Bhˆœûj¸âS©À\¬·k‘BiHœúÒ¸ªS)Äœ­·m‘Bj(œúJ¸‚R±ÈÜ®¶—oQBj¨œùš¸RRéȯ¶—qBkœøò¸*S!Ì\°¶—sBkÈœøb¸RÉÐܱ¶tÑBl¨œ÷Ò¸R1в¶vÑBmhœ÷*¸*RÔ\³µ—yBnHœö‚¸:RiØÜ´µ—{QBoHœõú¸"Ráܵµ}QBpœõb¸S!Üœ¶µ‘BpÈœôº·úR©àÜ·´—QBq¨œô ·âRà\¸´—ƒQBr¨œóZ¸JQÑäܹ´…QBsÈœò’¸zQÙ亴†ÑBtèœñ¸zRIä\»´ˆ‘Bvœñ¸bR蜼³—ŠÑBwHœð‚¸jR‰èܽ³—QBxhœï¸ÊR‰è¾³Byhœî⸚R迳ÑBz¨œî"¸RRéèÀ³’‘B|Hœír¸S1èÜÁ²—”‘B}ˆœìª·ºSaèܲ——B~ˆœëê·‚R±è\ò™BHœë:·jQÁäIJ›B€Hœêª·êQiäœÅ±—QBHœéú¸ZQ¹äƱ—Ÿ‘B‚Hœé"¸ZR!äœÇ±¡‘Bƒ(œèz¸2Rqàȱ£QB„œè¸RÙàœÉ±¥B„ÈœçZ·ÒSàʰ—§B…hœæª·¢R‰à\˰—¨ÑB†hœæ·rR1ÜṴ̈ªÑB‡Hœåš·JRAÜͰ­B‡èœå·JQÙܜί—¯QBˆˆœäŠ·RQyØϯ—±B‰Hœä ·ZQ)؜Я—²ÑB‰èœã’·jPÑØѯ´ÑBŠˆœã·ŠQԜү·QB‹œâ’·¢Q‘ÐÓ®—¹‘B‹¨œâ:·ÂQ±Ð ÜÔ®—¼BŒ(œáò·òQÁÌ \Õ®½ÑBŒhœá’¸RqÈ \Ö®¿QBŒÈœá"¸*RùÄ ×­—ÁQBhœàʸ*R±¼ Ø­—ÃQBèœàb¸"R!¸ Ù­—Å‘BŽ(œß긲R)´ \Ú­ÇQBŽˆœßj¸ÊR)¬ \Û­ÉBŽÈœß¸²R ¨ œÜ¬—ÊÑBœÞš¸jQѤݬ—ÍBhœÞ ¸ºQñœ\Þ¬—ÏB¨œÝr¹RA˜Ü߬ÑBœÜê¸òR˜\à¬ÓQB(œÜb¸ÂRÁ”Üá«—ÕQBhœÛʸÒRÙ\â«—×QBÈœÛ:¸ºRÁÜã«ÙB‘œÚª¸’RÑä«ÚÑB‘HœÚ ¸ŠR±œå«Ü‘B‘hœÙB¹ R¡檗ÞQB‘¨œØz¹2R‘œçª—à‘B‘Èœ×Ú¸ÚRYÜèªâÑB’œ×B¸ºRq”éªåB’hœÖЏÊR©˜œêªæÑB’Ȝո¢R¹˜œë©—èÑB“(œÕ¸rRÁœÜì©—ê‘B“¨œÔR¸:R‘ í©ì‘B”HœÓr¸RRA¤î©îÑB•œÒ²¸šRY¤益ñB•¨œÒ¸jRa¨ð¨—óQB–œÑz¸2RY¬Üñ¨—ôÑB–hœÐª¸rRQ°Üò¨ö‘B—œÏ긪R)°œó¨øQB—èœÏB¸‚RA´\ô§—ú‘B˜¨œÎЏJR¡´õ§—üÑB™(œÍâ¸R™¸Üö§—þÑB™¨œÍJ·êRY¼œ÷§‘Bš(œÌ·ÂRA¼\ø§QBšÈœÌ"·ºR)À\ù¦˜QB›hœËr·šQáÀú¦˜B›èœÊÚ·‚Q™ÄÜû¦˜ÑBœhœÊj·rQYÄÜü¦ BœÉâ·òQ!ÈÜý¦ BÈœÉ2¸âQ‰ÈÜþ¥˜Bž¨œÈйZRÌÜÿ¥˜ÑBŸHœÈ¹JRqÌ¥˜‘BŸÈœÇ‚¹R‘Ð¥QB HœÆÒ¸ÒRÐ]¥QB¡(œÆ:¸ÂR™Ô]¥‘B¢œÅº¸ªRÁÔ¤˜ÑB£œÅ¸ŠSÔ¤˜ÑB£ÈœÄR¸jSAÔ¤‘B¤ˆœÃ²¸RS1Ô¤ÑB¥HœÃ2¸"SAÔ¤!QB¦HœÂŠ·úRqÐ £˜#B§œÁÒ¸"Q™Ð] £˜$ÑB§èœÁJ¸zQ)Ì £&ÑB¨¨œÀÒ¸²Q±ÈÝ £)B©hœÀB¸òRÑÄ £*ÑB©èœ¿š¹JSÀ]¢˜,‘Bªhœ¾ú¹ŠRù¸¢˜.QB«œ¾z¹‚S´Ý¢˜0B«hœ½Ú¹ZS¬¢2B«¨œ½*¹2Rá¤]¢4B«èœ¼ª¹Rñœ¡˜6B¬hœ¼:¹S”Ý¡˜8B¬ˆœ»ª¸êRьݡ˜9ÑB¬ˆœ» ¸êRqˆÝ¡;ÑB¬Èœºr¸âR™€¡=‘B­œº¹2Rá|¡?QB­Hœ¹r¹jRÉtÝ ˜@ÑB­Hœ¸ª¹’S)pÝ ˜BÑB¬èœ·ú¹‚SApÝ EB¬èœ·z¹jSil GB­œ·¹¢S‰l] HÑB­œ¶Z¹âSql]Ÿ˜JQB¬ˆœµ¢ºSIlŸ˜LB¬hœµ*º*S9lÝ Ÿ˜NQB¬hœ´º¹ÊRáp!ŸPQB¬hœ´2¹bRYp"ŸRQB¬ˆœ³z¹ÊRYtÝ#ŸTB¬Èœ²ÂºJR‰x$ž˜VB­(œ±úºJR‰|%ž˜XQB­(œ±2ºRS)€Ý&žZB­(œ°rºzS™„'ž[‘B­hœ¯ººbS™ˆ(ž]B­Èœ¯º2SáŒÝ)˜^ÑB­èœ®rºTA*˜`ÑB®œ­ª¹ÒT”]+˜cQB®ˆœ¬ò¹ŠSi˜,eÑB¯Hœ¬J¹’SœÝ-gÑB°œ«‚¹âRÁ .œ˜i‘B°hœª¢¹ÒR ]/œ˜kQB°¨œ©â¹ºR¡¤0œ˜mQB±Hœ©*¹ÂR±¨1œoB±¨œ¨rºrRá¨Ý2œqB²œ§ª»BS1¬3œrÑB²¨œ¦Ò»JSQ°]4›˜tÑB³hœ¦»*S¡°5›˜wQB´(œ¥2» T´Ý6›yB´¨œ¤Z»SѸ7›z‘Bµhœ£¢»S¼]8›|QB¶(œ¢ê» S¡À]9š˜B¶Èœ¢ºêS±Ä:š˜QB·hœ¡BºÒSÈÝ;š˜ƒB¸Hœ ZººSaÐ<š„QB¹(œŸ’ºÂS‘Ô]=š†QBºœžÒºÒS‘Ü>šˆ‘BºèœòºªSäÝ?™˜Š‘B¼œº‚S©èÝ@™˜ŒQB½ˆœœZºzSyðA™ŽQB¿(œ›¢»SAø]B™BÀˆœšÂ»²SšC™‘‘Bœ™ò»²SÒD˜˜“‘BÃÈœ™Z»ŠT: ÝE˜˜–BÅhœ˜Â»:TjÝF˜˜˜BÆÈœ˜ »ZT ÝG˜™ÑBÈHœ—J»¢S²H˜›‘BÊ(œ–¢»‚S’ ÝI˜QBÌhœ–»jSÊ$ÝJ—˜ŸQBΈœ•¢»âSò(K—˜¡QBÐ(œ•¼BT(L—˜£BѨœ”B¼:T:(]M—¥BÓˆœ“¢»òTJ(ÝN—§QBÕˆœ“*¼T2(O–˜©B×(œ’ª»úT2$]P–˜ª‘Bبœ’ »òTj$ÝQ–˜¬QBÚHœ‘b»ÚT* R–®ÑBÜHœÒ»êSêS–°ÑBݨœR¼"SâÝS –±QBݨœR¼*SêÝT–³BÞˆœª¼ZT ]U•˜µB߈œ¼JTV•˜·Bá(œŽr»êSÊ ÝW•˜¹Bâèœâ¼BS²]X•»BäœJ½:T2Y•¼QBä蜌¢½šTºÝZ•¾QBåÈœŒ ½RTáü[”˜ÀÑB看b¼ÒTÙø]\”˜ÂÑBè(œŠº¼ŠT±ô]”˜Ä‘Bé(œŠ"¼bT‰ðÝ^”Æ‘Bê(œ‰’¼2T¡ì_”ÉQBë(œ‰¼BTÁè]`“˜ËB윈‚¼šT±äa“˜ÍBìÈœ‡Ò¼ŠTqàb“˜Ï‘Bíhœ‡:¼:TiØÝc“Ñ‘Bîhœ†º¼"TaÔÝd“Ó‘Bï(œ†B¼ºT©ÐÝe’˜ÕQB靖…’¼ªTÁÌÝf’˜×QBðHœ„â¼jUÌÝg’˜ÙBð蜄:¼*TùÈÝh’ÛQBñˆœƒš»úTqÄÝi’ÝBò(œ‚â¼bTAÀj’ßBòÈœ‚2¼¢T!Àk‘˜áB󨜒¼‚T1¼l‘˜ãBôˆœ€ê¼jTá¼m‘˜å‘Bõœ€2¼’U¸n‘ç‘Bõhœм’T™¸o‘é‘Böœ~ò¼‚T™´p‘ëBöˆœ~B¼ºT‘´q˜ìÑBöÈœ}н"Ty´r˜ïB÷Hœ|Ú½TA´sñÑBøœ|B½T)°tô‘Bø¨œ{ª½¢Tq°]uö‘Bùœzê½âT¡°]v˜øBùhœz*½ºTÙ¬]w˜ùÑBúœyš½ŠU¬x˜ûÑBúèœy½ZU©¨ÝyýÑBûhœxJ½"VQ¨ÝzÿÑBûÈœwмúV¤{ÑBüHœvê¼ÊUÑ |Ž™ÑBüÈœv:¼ÚUaœ]}Ž™BýHœu‚½bU)œ~ŽQBý¨œtª½ŠTјŽ QBýèœsÚ½’UQ˜€Ž BþHœs*½rU©”Ž ‘BþhœrZ½:U™”‚™‘Bþ¨œqz½ TÑ”ƒ™‘Bÿœp¼êT ”„™‘Bÿˆœp*½SÙ”…‘BÿÈœo‚½bTa”]†QBÿèœn’½¢U1˜]‡QBÿèœm²½ºUɘˆŒ™‘Chœm½šUᜉŒ™Cœlz½ºUá ŠŒÑCHœkÒ¾rUá¤Ý‹Œ!C¨œk¾’U©¬ÝŒŒ#QC(œjr¾2U¹°Ý‹™%‘CèœiÒ½ÒUÁ´Ž‹™'ÑChœi½zU鼋™)ÑCœhZ½UYÀ‹+ÑCÈœg¼ºT©Ä‘‹-‘C¨œg2¼¢TAÈ]’‹/QCˆœf‚¼’T±Ì]“‹1CHœe²¼ŠU™Ð”Š™3CHœe ¼ŠU©ÐÝ•Š™5C Hœd’¼šUAÔ]–Š7C Hœd½bU Ô—Š9QC (œcJ½ºU!ИŠ;C èœb¢½ºUyÐ]™Š<‘C ¨œb*½ÊU‘ÌÝš‰™>QC hœa²½ÒUyÈ›‰™@QC Èœa½ÂU)Àœ‰™BÑC èœ`нbTÙ¼‰ECˆœ`"½JT±´ž‰FÑC(œ_ʽJTɬŸ‰HQCˆœ_J½RUi   ˆ™JChœ^š½:Ui˜ ¡ˆ™LCˆœ^½"U1Œ Ý¢ˆ™M‘Cœ]š½Ty„ ]£ˆOChœ]Z¼úTAx ¤ˆP‘Chœ\ê¼úTÁp Ý¥ˆRQCèœ\R¼úT¹d ¦ˆTCèœ[â¼úT©\ §‡™VCœ[²½*TÁT ¨‡™WÑCèœ[н‚T±L ©‡™Y‘CHœ[½ÒTáH ª‡[QCˆœZr½êT±@ «‡]ChœYú¾T±< ݬ‡_CÈœYº¾ U8 Ý­‡`‘CˆœYR¾"U¹8 Ý®†™aÑC(œXÒ¾šU±4 ¯†™cQC ÈœXR¾’U14 °†™dÑC ¨œW꾚U!4 ±†™gC ˆœWŠ¿jUi0 ²†iC HœW ¿bUq0 ³†kC ÈœV’¿JU¡0 Ý´†mC hœVJ¿ZUÉ4 ݵ…™nÑC œV¿jV¡4 ¶…™pQC ˆœUj¿bVé4 ·…™qQC (œT¿:V‘4 ]¸…™rÑC HœTb¿VA4 ]¹…t‘C ˆœT:¾òV18 º…v‘C (œSò¿RUù8 »…xQC ¨œSz¿rU™4 ¼„™zC HœS¿ZUy4 ½„™|QC ˆœRº¿bU¡4 ]¾„™}ÑC ÈœRŠ¿²Uá0 ]¿„™C ˆœR*¿úV™, À„C èœQšÀVá( ÝÁ„ƒ‘C hœQ"À:Vé ]„…QC HœPÒÀW  Ù†ÑC HœPb¿êW) ă™ˆQC (œOÒ¿ºWY Ń™‰‘CˆœOJ¿‚VÑ ƃ™Š‘CÈœNú¿JUñÝǃ™ŒQCèœN¢¿ZU‘]ȃŽQC(œMú¿ZUAɃQCˆœMB¿ZUQʃ’QCHœL¿RUàü]Ë‚™”QC¨œLB¿ZVüÝÌ‚™–C¨œK¢¿‚UÈüÍ‚™—QC¨œJú¿šU°ü]΂™˜‘CèœJb¿²UàøÝÏ‚šÑCHœIÚ¿âUÈøЂChœI2À‚Uðü]Ñ‚ž‘BÿHœHrÀúV8üÒ™ŸÑBþ(œGºÁBV˜üÓ™¡QBýhœGÁ2Wü]Ô™£QBü¨œFRÁWqÕ™¥BûhœERÀÂWYÖ¦‘BúhœDjÀŠWi]רQBùˆœC²À:WIÝØªBø¨œBòÀW!]Ù€™¬QB÷ˆœBÀ2VéÝÚ€™®‘BöHœ@úÀZVqÛ€™°‘Bõ(œ@À:V) Ü€™²QBôhœ?"ÀRVa ÝÝ€³ÑBóˆœ>2À‚VaÞ€µ‘Bòˆœ=À‚V1]߀·QBñˆœ;êÀbVI]à€¹Bð¨œ:òÀjV‰á™º‘Bïèœ:"À‚V♼Bïœ9"À‚W㙾Bíèœ8 À‚Wy]äÀBìèœ7ÀBW]åÁQBìHœ6:À Vq]æÃB눜5rÀZVAçÄÑBꈜ4ZÀºV1 è~™ÆÑBéhœ3À¢V $Ýé~™ÈQB訜2À‚Vq$Ýê~™ÊBèhœ1ZÀZVá(Ýë~™ËÑBçèœ0zÀ:Vá,Ýì~ÍÑBç(œ/ZÀ:Va0Ýí~ÏÑBæhœ.BÀUù0Ýî~Ñ‘B娜-RÀ Ué4Ýï~ÓBåHœ,ŠÀRV)8ð}™Ô‘B䨜+¢ÀÊV‘<]ñ}™ÖÑBäHœ*‚ÁW)@ò}™ÙQBãèœ)jÀ¢WA@Ýó}Û‘B㈜(zÀBW¡D]ô}ÝBãHœ'jÀ WiHÝõ}ÞQBâÈœ&BÀ VéLö}ßÑBâHœ%¿òVQL÷|™áÑBâœ$ ¿ÒVqPø|™ãÑBáÈœ#¿²V¡Tù|™å‘B᨜!ú¿úVAT ú|çBáhœ ‚À‚V1X û|èQBáHœÀ‚V9\!ü|êBá(œúÀZV¡\!ý|ì‘Bá(œúÀVù`"þ{™îÑBá(œ²¿òV‘`"]ÿ{™ðÑBàèœ2¿òV9d"Þ{™ò‘BàÈœ¿ÊV!d#{™ôQBàÈœ¢¿¢V)d#^{ö‘Bà蜂¿ŠVAh#ž{øÑBàèœ"¿šV1h#Þ{úBàÈœš¿‚V!h$z™üBàèœ2¿ZV9h$z™þQBà蜿*Vh$^zšQB᜺¾êVh$^zBáœB¿:Uyh$ž z‘Bàèœ Ê¿šUyh$ž zQBáœ Š¿ŠUÁh$Þ zÑBáHœ ‚¿‚Uùh$Þ yš Bá(œ R¿ÒUéh% yš QBàèœÊÀjUùh%žyš ‘Bàèœ2ÀJU±h%Þy‘BàèœÊÀ Uáh&yQB᜚¿êVh&žy‘BáœJÀjVh'yBàèœÂÀòV)h'^yBàè›ÿ2ÀÊV9h'ÞxšBá›ýÒÀ‚Vil(^xš‘Bá(›übÀJV™l(ÞxšÑBá›úÊÀBV¡l)xQBá›ùÀRVal)žx QBáH›÷’ÀZVip)Þx"Bማö*ÀZV¹p)Þx#‘BáÈ›ôªÀ:V©p*wš%‘BáÈ›òò¿òV™p*wš(QBᨛñ:¿¢V©t*wš)ÑBáțﺿjVÑt*w+‘Bâh›îZ¿BVit)Þw-‘Bã›ìâ¿zVt)ž w/‘Bã›ë"¿ÒUÑx)^!w1‘Bâè›éj¿¢U±x(Þ"vš3QBãh›çú¿jUáx(^#vš5QB䛿²¿*VAx'Þ$vš7QBä(›åB¿"V |'^%v9Bãè›ãª¿2U™|&ž&v:ÑBä›â"¿BUa|&'vsgBîh›Åš¿’U¹ž?siBï›Ä¿jU^@ršjQB福Ãâ¿jUqÞArškÑBïÈ›ÂÊ¿jV”žBršmQBïè›Áª¿jV±”^CršoQBðh›Àª¿bV©”DrqQBñh›¿Ê¿2V!˜ÞErs‘Bò(›¾ê¿"U©˜žFruÑBòh›½Ú¿U±˜^GrwÑBòˆ›¼º¾âUј^HqšyQBó(›»Ú¾ÊUñ˜IqšzÑBô›»¾ºUñ˜Jqš|QBôÈ›º2¾¢UјÞKqš}ÑBõ(›¹¾‚UÁ˜ÞLqš‘Bõh›¸¾bU±˜ÞMq‚Bõè›·J¾U˜ÞNqƒÑBöˆ›¶z¾U1˜Oq…‘B÷›µz¾zU)˜Ppš‡QB÷h›´Z¾‚UY˜Qpšˆ‘B÷蛳b¾bU±˜RpšŠ‘Bøh›²Š¾:V˜SpšŒÑBøÈ›±Š½úUá˜TpBùH›°R½âUY˜Up‘Bù蛯"½ºTñ˜Vp’ÑBú¨›®2½’Tá˜ÞWp”QBû(›­r½šTјžXoš•ÑBû¨›¬š½ÚTáœ^Yoš—‘Bû蛫r½ÂTñœ^Zoš™ÑBüH›ªj½¢U9œ[oš›ÑBüÈ›©ª½‚UI Þ\oQBýˆ›¨ú½bU) ž]ož‘BþH›¨½êU ^^o Bþ¨›§¾JTù _o¡ÑBÿH›¦ ¾U `o¤QBÿ蛥b½ÂU1 anš§QCˆ›¤º½ÂTá bnš©C›£Ê¾T cnšªQCh›¢ª¾ Ti dn¬C›¡Ê¾ TÁœen®C¨›¡½òUœ^fn°CH› R¾:U˜žgn±QC蛟:¾ŠU)˜žhn³Ch›ž ¾jU9˜Þimš´ÑC›¾JUI˜jmš¶ÑCˆ›œj¾ U”^kmš¸ÑC¨››¢¾*T™”žlmšº‘CÈ›šŠ¾ºT‰˜mm¼Cè›™b¿U!˜^nm½‘C¨›˜r¾ÒUy˜žom¿Ch›—ª¾šUÉœpmÁCÈ›–¢¾zU¹œ^qlšÂÑC›•r¾bUq ÞrlšÄQCÈ›”Z¾JUI¤slšÆC ˆ›“j¾:U¨žtlšÈC H›’‚¾’U‘¨ÞulÊC (›‘Z¿ZU©¬^vlËÑC 蛿zV°žwlÍÑC 蛿V ´ÞxlÏÑC 蛎*¾ºV¸ykšÑ‘Cè›J¾bV¸^zkšÓQCÈ›Œ ¾2U±¼^{kšÔÑCÈ›Š²¾U)Àž|kšÖQCè›‰Š¾T¡ÀÞ}kšØCh›ˆº¾TùÄÞ~kÙÑC¨›‡ò¾JU9ÄÞkÜQC¨›†â¿UyÄÞ€kÞÑCˆ›…r¿U¡È jšáC蛄2¾²U‘È ‚jšãCh›ƒJ¾bU‰È ƒjšåC¨›‚‚¾2UqÈ „jšæQC¨›j¾ZU9ÈÞ…jšèCˆ›€*¾zU!ÈÞ†jê‘C›~ú¾ZUaÈÞ‡jìÑCˆ›}ú¾JUÈžˆjîC ¨›}¾jU™È^‰jïC!ˆ›{Ú¾ÒUyÈ^ŠišðÑC"h›z¢¾ÒUÈ‹išò‘C#h›yª¾¢TùÈÞŒišôQC$¨›xâ¿U1ÈžišõÑC%è›wò¿ºU±È^Žiš÷ÑC&è›vÂÀ*VñÌiúC'è›u¢À W9ÌÞiûÑC(è›tÒ¿ªVÉÌ^‘iý‘C*›t"¿2VÌ’iÿ‘C+H›s*¿:UÐÞ“h›ÑC,ˆ›qò¿rU9О”h›‘C-ˆ›pÊ¿ZTéÐ^•h›QC.¨›oò¿BUÐÞ–h›ÑC0›oJ¿bU)О—hQC1H›nrÀ:U‰Ð^˜h ÑC2(›mJÀÊUÑÐÞ™h ‘C3›l2ÀºUáÌžšh ‘C4H›krÀbU¹Ì›hÑC5¨›jêÀ2U‰ÌÞœg›‘C6ˆ›j:À¢UiÈ^g›C7›i*ÀÚUqÈžg›ÑC7È›hÀÚU™ÄÞŸg›QC8È›gJÀÚUÙÄž gC:(›fÊÀúVÀ^¡g‘C;›f"Á2V¼¢g‘C;H›e:ÁbVù¼£gQC;¨›dRÁ’W1¸¤gQC(›bJÁÊV9°^§f›$‘C>ˆ›a:Â2VY°ž¨f›%ÑC>è›`2ÂVI°Þ©f›'QC?¨›_jÁêVi°ªf(ÑC@ˆ›^ºÁâV‰¬^«f*QCAH›]Ú‚Vá¬Þ¬f,CAÈ›\ºÃWY¬­f.CB(›[ªÂÒWy¬®f/ÑCC›ZÊÂrW‰¬^¯e›1QCDH›Z ÂZWi°ž°e›2ÑCDÈ›YÂRVù°ž±e›4QCE›WÚÂ*VÁ°ž²e›5ÑCEh›VšÁòV¹°ž³e›7‘CFˆ›UÂÁÂVÁ´ž´e9CGè›U*Á’V™´^µe;CH¨›TjÁ’VI´^¶e=CHè›SRÁŠV‘´·e?CIH›R:ÁŠVѸ¸e@QCJH›QZÁ‚V±¸Þ¹d›AQCK¨›PºÁ¢V©¼žºd›BÑCLÈ›PÂ"V‰¼^»d›DQCM›O‚V©¼¼d›EÑCMh›MúÂÒW9ÀÞ½d›GQCNH›M¢WqÀž¾dICO¨›LrÂbWAÀ^¿dJÑCPÈ›KÊÂBVéÀÀdLQCQh›JÒÂ*VáÄžÀ dL‘CQh›JÒÂ*VéÄžÁdNCQè›IÒÂWÄ^ÂdO‘CRÈ›IÂW ÀÞÃc›QCT(›H‚ VéÀ^Äc›R‘CU(›Gê²VùÀÅc›TQCUˆ›Gà VéÀžÆc›VCUÈ›F*Ã*W1¼Çc›WÑCVh›EjÂÚW¸žÈcYQCWˆ›DêÂÂV¹¸^ÉcZÑCXh›DbÃV™´ÞÊc\QCXÈ›CªÃVѰžËc]‘CXè›BÚÃ*WI¬^Ìc_CYh›B2ÃBWy¨Íc`‘CZH›AªÃrWa¤ÞÎb›aÑCZè›A"ÃâWa¤žÏb›cÑCZè›@bÄ"W‰ ^Ðb›fQCZÈ›?’ÄrWùœ^Ñb›gÑC[(›>úÄBWé˜Òb›iC\›>ŠÄBWÁ˜Óbj‘C\ˆ›=òÄòX ”ÞÔbmC\H›=*ÅzXA”ÞÕboQC\›Ð¿;Ìð/Tÿÿÿÿà XíT8ÿÃ?ÿÿÿÿÿý‚¹<¿€ ¸eÈùòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁOú¿ø~ÿÿÿÿÿÿÿÿÿÿÿïéÿïéÿÿÿð'öFÿßÙn˜Œ?ÿ÷èÿýÿÿÿÿÿÿ€ÿ¿Gÿÿÿÿÿÿÿÿÿÿ÷ýÿÿÅ­¬Œ­Ä ìàcµ–øŽ×ÁèòÎ:îÇÿÿÿÿþØþØO{ÿü._ÿÿÿÿÿä ~ø Œ@ÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿüzÿ¦ÿ€èÿÿÿïúGÿÿÿÿþþÿþþÿÿÿÿd}ý¨é‡€Wÿÿ~ÿßÿÿÿÿÿøÿûôÿÿÿÿÿÿÿÿÿÿßÿüQÀ„äÊÚÊÜ@@@@@@@@@@@@@@¾Î0H° ® ? ©9¤çO ÿÿÿÿà ˆmk•ÿÏ¡ÿÿÿÿÿþAàDGï€@˜Â 'K€ÿ#þOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿÔ§ÿÑÿÿÿÿÿÿÿÿÿÿÿýý ÿýý ÿÿÿþþÈ 5ûû#1Ó@±ÿþýÿ¿ÿÿÿÿÿðÿ÷èÿÿÿÿÿÿÿÿÿÿÿÿÿÿø¤99•ÕÉÕÁÁ¥¸€€€€€€€€€€€}œ `6ƒ˜’c=ÀˆàEŠsùÝÞ¸ÿÿÿÿÿÀ2ÞÚÈ/ÿßÿÿÿÿÿô¿ùÿÿÀA?ÈÈÿò?äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðýÿÿÿÿÿÿÿÿÿÿÿßÒ?ÿßÒ?ÿÿÿàO삯¿²X1¿ÿïÑÿûÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠT’[››Ý™\ˆÙÀÆeŠÑ!m¢ã|¦ÿ!çÿÿÿÿü!²í­oÿù,?ÿÿÿÿÿ°;‹èýð_ÿ#þOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿÔ§ÿÑÿÿÿÿÿÿÿÿÿÿÿýý ÿýý ÿÿÿþþÉ`4ûû%!Ó@»ÿþýÿ¿ÿÿÿÿÿðÿ÷èÿÿÿÿÿÿÿÿÿÿÿÿÿÿø¥¥5…‘•‰ÕÉœ€€€€€€€€€€€}œ `65F’EZ€”ÀKÊoùÚ˜ÿÿÿÿÿÀ2ëZÀlÿ‹CÿÿÿÿÿüŸøèÿÿÀÁÇ@Qù ?5 ÿÈÿ“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿþnÕ)ÿÀôÿÿÿÿÿÿÿÿÿÿÿHÿÿHÿÿÿÿ?²0>þÉ`0tÅP&ÿÿ¿Gÿïÿÿÿÿÿüÿýú?ÿÿÿÿÿÿÿÿÿÿ¿ïÿþ)‰Lindenberg _g ê¤ Ðø&讜.x×¶?ÿÿÿÿð †°6ªËßÿáôÿÿÿÿÿý§žPàP<?üù?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿà§ýü?Gÿÿÿÿÿÿÿÿÿÿÿ÷ô€ÿ÷ô€ÿÿÿøû €ïì‚LF¯ÿûôþÿÿÿÿÿÿÀ?ÿߣÿÿÿÿÿÿÿÿÿÿûþÿÿâ™GVW76VÆF÷&böp1€×šVG?.!Ái½'%yÿÿÿÿÿÈm—l¦«ÿþÚÏÿÿÿÿÿòáþ?|Fá8°ùòÿÿÿÿÿÿÿÿÿÿÿÿÿÿǯúa?ø~ÿÿþÿ ÿÿÿÿïéÿïéÿÿÿð'öKWßÙ, n˜–ÿÿ÷èÿýÿÿÿÿÿÿ€ÿ¿Gÿÿÿÿÿÿÿÿÿÿ÷ýÿÿÅ6Él.nl­„ìàc¯4舴)ƒÓάóÇÿÿÿÿþØÖÖSCÿü¨ÿÿÿÿÿäÿÃïÿþ ~@ÿ‘ÿ'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿêSÿ€èÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿÿeýý•@té‹@Qÿÿ~ÿßÿÿÿÿÿÿÿÿÿÿÿûôÿÿÿÿÿÿÿÿÿÿÿÿÿüSª˜ÊÒàôÒÎZ¦ÆÐÖÊêÈÒèô@@¾Î0úI*²`Rø)×6Œï/\ÿÿÿÿà k­V¶ÿÎÿÿÿÿÿû!ÄnF¡€@ˆÃp$mÿ#þOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿÔ§ÿÑÿÿÿÿÿÿÿÿÿÿÿýý ÿýý ÿÿÿþþÊ;ûû%1ÓÀ™ÿþýÿ¿ÿÿÿÿÿÿÿÿÿÿÿ÷èÿÿÿÿÿÿÿÿÿÿÿÿÿÿø§¡ɕ͑•¸µ-±½ÑéÍ¡”€€}œ `5Ö&z_ ÃðbÒf©â_ÿÿÿÿÿÀ2ÊÚ ¬ÿÿŽÿÿÿÿÿñ yBÀA°ÿò?äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ýJðýÿÿÿÿÿÿÿÿÿÿÿßÒ?ÿßÒ?ÿÿÿàOì‚_¿²]1 ÿÿïÑÿûÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠ~“Y\˜\™ËP˜\ÙZ[\ˆÙÀÆX²9$6I§$öœÙìoÿÿÿÿü!²í²oÿú¼?ÿÿÿÿÿÈ<ýð…ÿäÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿éDÿàú?ÿÿûþ€ÿÿÿÿÿ¿¤ÿ¿¤ÿÿÿÀŸÙ|ßeð-:bøÿÿߣÿ÷ÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿß÷ÿÿ&²´·4·3²·/³Œ³ÙÒDü0!4§J¥;³ÛÿÿÿÿøCZ›X=ÿÿñÿÿÿÿÿxò{à087þGüŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿ©Oþ£ÿÿÿÿÿÿÿÿÿÿÿûú@ÿûú@ÿÿÿü ý•@u÷öU[¦(oÿýú?ÿÿÿÿÿÿàÿïÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿñSê3“ s[3«“¡zk Kqû8ÀjØÐ#øê@ TÚs®½1ÿÿÿÿÿ€d6Sµ¨OÿÿN'ÿÿÿÿÿùq#¾‚ã ÿäÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ¿éŒÿàú?ÿÿûþ€ÿÿÿÿÿ¿¤ÿ¿¤ÿÿÿÀŸØPŸ`ðºa@ÿߣÿ÷ÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿÿÿÿÿÿÿß÷ÿÿV¤7³³Œ°ÏIL%³äI³ 731 M OF IMAGE SPECTRUM AT LOW WAVE NUMBERS M 0 0 14 022098 WAVELENGTH SPREAD (WAVELENGTH > 731 M) AT LOW WAVE NUMBERS M 0 0 14 022099 MEAN DIRECTION AT LOW WAVE NUMBERS (WAVELENGTH > 731 M) DEGREE TRUE 0 0 9 022100 DIRECTION SPREAD AT LOW WAVE NUMBERS (WAVELENGTH > 731 M) DEGREE 0 0 9 022101 TOTAL ENERGY (WAVELENGTH > 731 M) AT LOW WAVE NUMBERS NUMERIC 0 0 31 022120 TIDE STATION AUTOMATED WATER LEVEL CHECK CODE TABLE 022120 0 0 5 022121 TIDE STATION MANUAL WATER LEVEL CHECK CODE TABLE 022121 0 0 5 022122 TIDE STATION AUTOMATED METEOROLOGICAL DATA CHECK CODE TABLE 022122 0 0 5 022123 TIDE STATION MANUAL METEOROLOGICAL DATA CHECK CODE TABLE 022123 0 0 5 022141 SEA SURFACE TEMPERATURE (15 DAY RUNNING MEAN) K 2 0 15 022150 NUMBER OF 18 HZ VALID POINTS FOR KU BAND NUMERIC 0 0 10 022151 KU BAND OCEAN RANGE M 3 0 31 022152 STD OF 18 HZ KU BAND OCEAN RANGE M 3 0 16 022153 NUMBER OF 18 HZ VALID POINTS FOR S BAND NUMERIC 0 0 10 022154 S BAND OCEAN RANGE M 3 0 31 022155 STD OF 18 HZ S BAND OCEAN RANGE M 3 0 16 022156 KU BAND SIGNIFICANT WAVE HEIGHT M 3 0 16 022157 STD 18 HZ KU BAND SIGNIFICANT WAVE HEIGHT M 3 0 16 022158 S BAND SIGNIFICANT WAVE HEIGHT M 3 0 16 022159 STD 18 HZ S BAND SIGNIFICANT WAVE HEIGHT M 3 0 16 022160 NORMALIZED INVERSE WAVE AGE NUMERIC 6 0 21 022161 WAVE SPECTRA M**4 4 0 27 022192 SPECTRAL PERIOD S 2 0 13 022193 MEAN WAVENUMBER 1/M 5 0 15 022194 PEAK WAVENUMBER 1/M 5 0 15 022195 MEAN WAVE PROPAGATION DIRECTION DEGREE 1 0 13 022196 PEAK WAVE PROPAGATION DIRECTION DEGREE 1 0 13 022197 DIRECTION SPREAD DEGREE 1 0 13 022198 VARIANCE SPECTRAL DENSITY M**2*S/RAD 4 0 18 022199 CORRELATION COEFF OF SIMULATED FG AND OBSERVED SAR SPECTRUM NUMERIC 4 -10000 15 022200 CORRELATION COEFF OF SIMULATED BF AND OBSERVED SAR SPECTRUM NUMERIC 4 -10000 15 022201 CORRELATION COEFF OF OCEAN WAVE FG AND EXTRACTED WAVE SPECTRUM NUMERIC 4 -10000 15 022202 ERROR BETWEEN FIRST GUESS AND OBSERVED SAR NUMERIC 5 0 21 022203 ERROR BETWEEN SIMULATED AND OBSERVED SAR NUMERIC 5 0 21 022204 MEAN PERIOD OF WAVES SECOND 2 0 13 022205 SPECTRAL DENSITY M**2*S/RAD 4 0 25 022206 PEAK PERIOD OF WAVES SECOND 2 0 13 022207 MEAN WAVE PERIOD S 1 0 10 022208 PEAK PERIOD OF 1D SPECTRA S 1 0 10 022209 COEFICIENT OF DRAG WITH WAVES NUMERIC 6 0 13 022210 MEAN SQUARE SLOPE OF WAVES NUMERIC 4 -10000 14 022211 COEFICIENT OF DRAG WITH WAVES NUMERIC 6 0 17 022243 STANDARD DEVIATION SIGNIFICANT WAVE HEIGHT M 2 0 10 023001 ACCIDENT EARLY NOTIFICATION-ARTICLE APPLICABLE CODE TABLE 023001 0 0 3 023002 ACTIVITY OR FACILITY INVOLVED INCIDENT CODE TABLE 023002 0 0 5 023003 TYPE OF RELEASE CODE TABLE 023003 0 0 3 023004 COUNTERMEASURES TAKEN NEAR BORDER CODE TABLE 023004 0 0 3 023005 CAUSE OF INCIDENT CODE TABLE 023005 0 0 2 023006 INCIDENT SITUATION CODE TABLE 023006 0 0 3 023007 CHARACTERISTICS OF RELEASE CODE TABLE 023007 0 0 3 023008 STATE OF CURRENT RELEASE CODE TABLE 023008 0 0 2 023009 STATE OF EXPECTED RELEASE CODE TABLE 023009 0 0 2 023016 POSSIBILITY OF SIGNIFICANT CHEMICAL TOXIC HEALTH EFFECT CODE TABLE 023016 0 0 2 023017 FLOW DISCHARGE OF MAJOR RECIPIENT M**3/S 6 0 20 023018 RELEASE BEHAVIOUR OVER TIME CODE TABLE 023018 0 0 3 023019 ACTUAL RELEASE HEIGHT M 0 -15000 17 023021 EFFECTIVE RELEASE HEIGHT M 0 -15000 17 023022 DISTANCE OF RELEASE POINT OR SITE OF INCIDENT M 0 0 24 023023 MAIN TRANSPORT SPEED IN THE ATMOSPHERE M/S 1 0 12 023024 MAIN TRANSPORT SPEED WATER M/S 2 0 13 023025 MAIN TRANSPORT SPEED IN GROUND WATER M/S 2 0 13 023027 MAIN TRANSPORT DIRECTION IN THE ATMOSPHERE DEGREE TRUE 0 0 9 023028 MAIN TRANSPORT DIRECTION IN WATER DEGREE TRUE 0 0 9 023029 MAIN TRANSPORT DIRECTION IN GROUND WATER DEGREE TRUE 0 0 9 023031 POSSIBILITY THAT PLUME WILL ENCOUNTER PRECIPITATION IN STATE IN CODE TABLE 023031 0 0 2 023032 PLUME WILL ENCOUNTER CHANGE IN WIND DIRECTION AND/OR SPEED FLAG CODE TABLE 023032 0 0 2 024001 ESTIMATE OF AMOUNT OF RADIOACTIVITY RELEASED UP TO SPECIFIED TIM Bq -11 0 28 024002 ESTIMATED MAXIMUM POTENTIAL RELEASE Bq -11 0 28 024003 COMPOSITION OF RELEASE CODE TABLE 024003 0 0 5 024004 ELEMENT NAME CCITTIA5 0 0 16 024005 ISOTOPE MASS NUMERIC 0 0 9 024011 DOSE mSv 2 0 32 024012 TRAJECTORY DOSE (DEFINED LOCATION AND EXPECTED TIME OF ARRIVAL) mSv 2 0 32 024013 GAMMA DOSE IN AIR ALONG THE MAIN TRANSPORT PATH(DEFINED LOCATION mSv 2 0 32 024021 AIR CONCENTRATION(OF NAMED ISOTOPE TYPE INCLUDING GROSS BETA Bq/M**3 2 0 32 024022 CONCENTRATION IN PRECIPITATION ( OF NAMED ISOTOPE TYPE) Bq/L 2 0 32 024023 PULSE RATE OF BETA RADIATION 1/S 1 0 14 024024 PULSE RATE OF GAMMA RADIATION 1/S 1 0 14 025001 RANGE-GATE LENGTH M -1 0 6 025002 NUMBER OF GATES AVERAGED NUMERIC 0 0 4 025003 NUMBER OF INTEGRATED PULSES NUMERIC 0 0 8 025004 ECHO PROCESSING CODE TABLE 025004 0 0 2 025005 ECHO INTEGRATION CODE TABLE 025005 0 0 2 025006 Z TO R CONVERSION CODE TABLE 025006 0 0 3 025007 Z TO R CONVERSION FACTOR NUMERIC 0 0 12 025008 Z TO R CONVERSION EXPONENT NUMERIC 2 0 9 025009 CALIBRATION METHOD FLAG TABLE 025009 0 0 4 025010 CLUTTER TREATMENT CODE TABLE 025010 0 0 4 025011 GROUND OCCULTATION CORRECTION (SCREENING) CODE TABLE 025011 0 0 2 025012 RANGE ATTENUATION CORRECTION CODE TABLE 025012 0 0 2 025013 BRIGHT-BAND CORRECTION FLAG TABLE 025013 0 0 2 025014 AZIMUTH CLUTTER CUT-OFF NUMERIC 0 0 12 025015 RADOME ATTENUATION CORRECTION FLAG TABLE 025015 0 0 2 025016 CLEAR-AIR ATTENUATION CORRECTION dB/M 5 0 6 025017 PRECIPITATION ATTENUATION CORRECTION FLAG TABLE 025017 0 0 2 025018 A TO Z LAW FOR ATTENUATION FACTOR NUMERIC 7 0 6 025019 A TO Z LAW FOR ATTENUATION EXPONENT NUMERIC 2 0 7 025020 MEAN SPEED ESTIMATION CODE TABLE 025020 0 0 2 025021 WIND COMPUTATION ENHANCEMENT FLAG TABLE 025021 0 0 8 025025 BATTERY VOLTAGE V 1 0 9 025026 BATTERY VOLTAGE (LARGE RANGE) V 1 0 12 025028 OPERATOR OR MANUFACTURER DEFINED PARAMETER NUMERIC 1 -16384 15 025030 RUNNING MEAN SEA-SURFACE TEMPERATURE USAGE CODE TABLE 025030 0 0 2 025032 WIND PROFILER MODE INFORMATION CODE TABLE 025032 0 0 2 025033 WIND PROFILER SUBMODE INFORMATION CODE TABLE 025033 0 0 2 025034 WIND PROFILER QUALITY CONTROL TEST RESULTS FLAG TABLE 025034 0 0 4 025036 ATMOSPHERICS LOCATION METHOD CODE TABLE 025036 0 0 4 025040 CO2 WIND PRODUCT DERIVATION CODE TABLE 025040 0 0 4 025041 MOVING PLATFORM DIRECTION REPORTING METHOD CODE TABLE 025041 0 0 2 025042 MOVING PLATFORM SPEED REPORTING METHOD CODE TABLE 025042 0 0 2 025043 WAVE SAMPLING INTERVAL (TIME) S 4 0 15 025044 WAVE SAMPLING INTERVAL (SPACE) M 2 0 14 025045 HIRS CHANNEL COMBINATION FLAG TABLE 025045 0 0 21 025046 MSU CHANNEL COMBINATION FLAG TABLE 025046 0 0 5 025047 SSU CHANNEL COMBINATION FLAG TABLE 025047 0 0 4 025048 AMSU-A CHANNEL COMBINATION FLAG TABLE 025048 0 0 16 025049 AMSU-B CHANNEL COMBINATION FLAG TABLE 025049 0 0 6 025050 PRINCIPAL COMPONENT SCORE NUMERIC 4 -131072 18 025051 AVHRR CHANNEL COMBINATION FLAG TABLE 025051 0 0 7 025053 OBSERVATION QUALITY FLAG TABLE 025053 0 0 12 025054 SSMIS SUBFRAME ID NUMBER NUMERIC 0 0 5 025055 MULTIPLEX HOUSEKEEPING K 2 0 16 025060 SOFTWARE IDENTIFICATION NUMERIC 0 0 14 025061 SOFTWARE IDENTIFICATION CCITTIA5 0 0 96 025070 MAJOR FRAME COUNT NUMERIC 0 0 4 025071 FRAME COUNT NUMERIC 0 0 5 025075 SATELLITE ANTENNA CORRECTIONS VERSION NUMBER NUMERIC 0 0 5 025076 LOG_10 OF (TEMPERATURE-RADIANCE CENTRAL WAVENUMBER) FOR ATOVS LOG (1/M) 8 0 30 025077 BANDWIDTH CORRECTION COEFFICIENT 1 for ATOVS NUMERIC 5 -100000 18 025078 BANDWIDTH CORRECTION COEFFICIENT 2 FOR ATOVS NUMERIC 5 0 17 025079 ALBEDO-RADIANCE SOLAR FILTERED IRRADIANCE FOR ATOVS W/M**2 4 0 24 025080 ALBEDO-RADIANCE EQUIVALENT FILTER WIDTH FOR ATOVS M 10 0 14 025085 FRACTION OF CLEAR PIXELS IN HIRS FOV NUMERIC 0 0 7 025086 DEPTH CORRECTION INDICATOR CODE TABLE 025086 0 0 2 025091 STRUCTURE CONSTANT OF THE REFRACTION INDEX (Cn2) dB 3 -18192 13 025092 ACOUSTIC PROPAGATION VELOCITY M/S 2 28000 14 025093 RASS COMPUTATIONAL CORRECTION FLAG TABLE 025093 0 0 8 025095 ALTIMETER STATE FLAG FLAG TABLE 025095 0 0 2 025096 RADIOMETER STATE FLAG FLAG TABLE 025096 0 0 5 025097 THREE DIMENSIONAL ERROR ESTIMATE OF THE NAVIGATOR ORBIT CODE TABLE 025097 0 0 4 025100 XBT/XCTD FALL RATE EQUATION COEFFICIENT A NUMERIC 5 0 20 025101 XBT/XCTD FALL RATE EQUATION COEFFICIENT B NUMERIC 5 -500000 21 025102 NUMBER OF MISSING LINES EXCLUDING DATA GAPS NUMERIC 0 0 8 025103 NUMBER OF DIRECTIONAL BINS NUMERIC 0 0 8 025104 NUMBER OF WAVELENGHT BINS NUMERIC 0 0 8 025105 FIRST DIRECTIONAL BIN DEGREES 3 0 19 025106 DIRECTIONAL BIN STEP DEGREES 3 0 19 025107 FIRST WAVELENGHT BIN M 3 0 29 025108 LAST WAVELENGHT BIN M 3 0 29 025110 IMAGE PROCESSING SUMMARY FLAG TABLE 025110 0 0 10 025111 NUMBER OF INPUT DATA GAPS NUMERIC 0 0 8 025120 RA2_L2_PROCESSING FLAG CODE TABLE 025120 0 0 2 025121 RA2_L2_PROCESSING QUALITY % 0 0 7 025122 HARDWARE CONFIGURATION FOR RF CODE TABLE 025122 0 0 2 025123 HARDWARE CONFIGURATION FOR HPA CODE TABLE 025123 0 0 2 025124 MWR L2 PROCESSING FLAG CODE TABLE 025124 0 0 2 025125 MWR L2 PROCESSING QUALITY % 0 0 7 025126 MODEL DRY TROPOSPHERIC CORRECTION M 3 -32768 16 025127 SEA SURFACE HEIGHT CORRECTION DUE TO PRESSURE LOADING M 3 -32768 16 025128 MODEL WET TROPOSPHERIC CORRECTION M 3 -32768 16 025129 MWR DERIVED WET TROPOSPHERIC CORRECTION M 3 -32768 16 025130 RA2 IONOSPHERIC CORRECTION ON KU BAND M 3 -32768 16 025131 IONOSPHERIC CORRECTION FROM DORIS ON KU BAND M 3 -32768 16 025132 IONOSPHERIC CORRECTION FROM MODEL ON KU BAND M 3 -32768 16 025133 SEA STATE BIAS CORRECTION ON KU BAND M 3 -32768 16 025134 RA2 IONOSPHERIC CORRECTION ON S BAND M 3 -32768 16 025135 IONOSPHERIC CORRECTION FROM DORIS ON S BAND M 3 -32768 16 025136 IONOSPHERIC CORRECTION FROM MODEL ON S BAND M 3 -32768 16 025137 SEA STATE BIAS CORRECTION ON S BAND M 3 -32768 16 025138 AVERAGE SIGNAL TO NOISE RATIO NUMERIC 0 -2048 12 025193 ATTENUATION CORRECTION ON SIGMA0 dB 3 0 14 025194 MAJOR FRAME COUNT NUMERIC 0 0 4 025197 ANTENNA CORRECTIONS VERSION NUMBER NUMERIC 0 0 5 025198 LOG (TEMP-RAD CENTRAL WAVE NUMBER) 1/M 8 0 30 025199 BANDWIDTH CORRECTION COEFFICIENT 1 NUMERIC 4 -10000 15 025200 BANDWIDTH CORRECTION COEFFICIENT 2 NUMERIC 5 0 17 025201 ALBEDO-RAD SOLAR FILTERED IRRADIANCE NUMERIC 4 0 24 025202 ALBEDO-RAD EQUIVALENT FILTER WIDTH NUMERIC 10 0 14 025203 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 25081 0 0 31 025204 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 25082 0 0 31 025205 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 25083 0 0 31 025206 FOV QUALITY FLAGS FOR ATOVS FLAG TABLE 25084 0 0 31 026001 PRINCIPAL TIME OF DAILY READING IN UTC OF MAXIMUM TEMPERATURE HOUR 1 0 12 026002 PRINCIPAL TIME OF DAILY READING IN UTC OF MINIMUM TEMPERATURE HOUR 1 0 12 026003 TIME DIFFERENCE MINUTE 0 -1440 12 026010 HOURS INCLUDED FLAG TABLE 026010 0 0 26 026020 DURATION OF PRECIPITATION MINUTE 0 0 11 026193 YEAR YEAR 0 0 12 026194 MONTH MONTH 0 0 4 026195 DAY DAY 0 0 6 026196 HOUR HOUR 0 0 5 026197 MINUTE MINUTE 0 0 6 026198 SECOND SECOND 0 0 6 026200 LOCATION WITHIN ASSIMILATION WINDOW IN TIME NUMERIC 6 0 20 026201 HOURS INCLUDED FLAG TABLE 26201 0 0 26 027001 LATITUDE(HIGH ACCURACY) DEGREE 5 -9000000 25 027002 LATITUDE(COARSE ACCURACY) DEGREE 2 -9000 15 027003 ALTERNATE LATITUDE DEGREE 2 -9000 15 027004 ALTERNATE LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 027020 SATELLITE LOCATION COUNTER NUMERIC 0 0 16 027021 SATELLITE SUBLOCATION DIMENSION NUMERIC 0 0 16 027031 IN DIRECTION OF 0 DEGREES LONGITUDE, DISTANCE FROM THE EARTH'S C M 2 -1073741824 31 027035 LENGTH OF PHENOMENON M -3 0 13 027080 VIEWING AZIMUTH ANGLE DEGREE TRUE 2 0 16 027193 SOLAR AZIMUTH DEGREE TRUE 2 0 16 028001 LONGITUDE(HIGH ACCURACY) DEGREE 5 -18000000 26 028002 LONGITUDE(COARSE ACCURACY) DEGREE 2 -18000 16 028003 ALTERNATE LONGITUDE DEGREE 2 -18000 16 028004 ALTERNATE LONGITUDE (HIGH ACCURACY) DEGREE 5 -18000000 26 028031 IN DIRECTION 90 DEGREES EAST,DISTANCE FROM THE EARTH'S CENTRE M 2 -1073741824 31 028035 WIDTH OF PHENOMENON M -3 0 13 029001 PROJECTION TYPE CODE TABLE 029001 0 0 3 029002 COORDINATE GRID TYPE CODE TABLE 029002 0 0 3 030001 PIXEL VALUE(4 BITS) NUMERIC 0 0 4 030002 PIXEL VALUE(8 BITS) NUMERIC 0 0 8 030004 PIXEL VALUE(16 BITS) NUMERIC 0 0 16 030021 NUMBER OF PIXELS PER ROW NUMERIC 0 0 12 030022 NUMBER OF PIXELS PER COLUMN NUMERIC 0 0 12 030031 PICTURE TYPE CODE TABLE 030031 0 0 4 030032 COMBINATION WITH OTHER DATA FLAG TABLE 030032 0 0 16 030193 POSITION NUMBER ALONG SCAN NUMERIC 0 0 8 031000 SHORT DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 1 031001 DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 8 031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 16 031011 DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 8 031012 EXTENDED DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 16 031021 ASSOCIATED FIELD SIGNIFICANCE CODE TABLE 031021 0 0 6 031031 DATA PRESENT INDICATOR FLAG TABLE 031031 0 0 1 031192 DATA PRESENT INDICATOR NUMERIC 0 0 1 033002 QUALITY INFORMATION CODE TABLE 033002 0 0 2 033003 QUALITY INFORMATION CODE TABLE 033003 0 0 3 033005 QUALITY INFORMATION (AWS DATA) FLAG TABLE 033005 0 0 30 033006 INTERNAL MEASUREMENT STATUS INFORMATION (AWS) CODE TABLE 033006 0 0 3 033007 % CONFIDENCE % 0 0 7 033020 QUALITY CONTROL INDICATION OF FOLLOWING VALUE CODE TABLE 033020 0 0 3 033021 QUALITY OF FOLLOWING VALUE CODE TABLE 033021 0 0 2 033022 QUALITY OF BUOY SATELLITE TRANSMISSION CODE TABLE 033022 0 0 2 033023 QUALITY OF BUOY LOCATION CODE TABLE 033023 0 0 2 033024 STATION ELEVATION QUALITY MARK (FOR MOBILE STATION) CODE TABLE 033024 0 0 4 033025 ACARS INTERPOLATED VALUES CODE TABLE 033025 0 0 3 033026 MIXING RATIO QUALITY CODE TABLE 033026 0 0 6 033027 LOCATION QUALITY CLASS (RANGE OF RADIUS OF 66% CONFIDENCE) CODE TABLE 033027 0 0 3 033030 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 033030 0 0 24 033031 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 033031 0 0 24 033032 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 033032 0 0 24 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS FLAG TABLE 033033 0 0 24 033035 MANUAL/AUTOMATIC QUALITY CONTROL CODE TABLE 033035 0 0 4 033036 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 033037 WIND CORRELATION ERROR FLAG TABLE 033037 0 0 20 033038 QUALITY FLAG FOR GROUND BASED GNSS DATA FLAG TABLE 033038 0 0 10 033040 CONFIDENCE INTERVAL % 0 0 7 033041 ATTRIBUTE OF FOLLOWING VALUE CODE TABLE 033041 0 0 2 033043 AST CONFIDENCE FLAG TABLE 033043 0 0 8 033044 ASAR QUALITY INFORMATION FLAG TABLE 033044 0 0 15 033047 MEASUREMENT CONFIDENCE DATA FLAG TABLE 033047 0 0 31 033048 CONFIDENCE MEASURE OF SAR INVERSION CODE TABLE 033048 0 0 2 033049 CONFIDENCE MEASURE OF WIND RETIEVAL CODE TABLE 033049 0 0 2 033050 GLOBAL GTSPP QUALITY FLAG CODE TABLE 033050 0 0 4 033051 ASAR QUALITY INFORMATION FLAG TABLE 033051 0 0 15 033052 S BAND OCEAN RETRACKING QUALITY FLAG TABLE 033052 0 0 21 033053 KU BAND OCEAN RETRACKING QUALITY FLAG TABLE 033053 0 0 21 033054 DATA EXTRACTION INDICATOR FLAG TABLE 033054 0 0 8 033192 TEM1 CONFIDENCE % 0 0 7 033193 DATA QUALITY 3 BIT CODE CODE TABLE 33193 0 0 3 033194 DATA QUALITY 2 BIT CODE CODE TABLE 33194 0 0 2 033195 ECMWF SAR QC INDICATOR CODE TABLE 33195 0 0 5 033196 ECMWF WAM QC INDICATOR CODE TABLE 33196 0 0 2 033197 ECMWF SAR INVERSION QC INDICATOR CODE TABLE 33197 0 0 3 033198 MINIMUM COST NUMERIC 4 0 14 033199 1D VAR TOTAL PRECIPITABLE WATER RETRIEVED ERROR(S) KG/M**2 2 0 11 033200 ANALYSIS REPORT EVENTS FLAG TABLE 33200 0 0 31 033201 ANALYSIS REPORT STATUS EVENT FLAG TABLE 33201 0 0 13 033202 ANALYSIS DATUM EVENT FLAGS (1) FLAG TABLE 33202 0 0 31 033203 ANALYSIS DATUM EVENT FLAGS (2) FLAG TABLE 33203 0 0 11 033204 ANALYSIS DATUM STATUS FLAGS FLAG TABLE 33204 0 0 21 033205 VARIATIONAL ANALYSIS BLACK LIST FLAG CODE TABLE 33205 0 0 4 033206 VARIATIONAL ANALYSIS QUALITY CONTROL FLAG CODE TABLE 33206 0 0 4 033207 VARIATIONAL ANALYSIS DEPARTURE FLAG CODE TABLE 33207 0 0 4 033208 VARIATIONAL ANALYSIS FIRST QUESS CHECK FLAG CODE TABLE 033208 0 0 4 033209 VARIATIONAL ANALYSIS FINAL FLAG CODE TABLE 33209 0 0 4 033210 INCREMENTAL VARIATIONAL ANALYSIS UPDATE NUMBER NUMERIC 0 0 7 033211 MINIMISATION SIMULATION NUMBER NUMERIC 0 0 10 033212 1D VAR ITERATION NUMBER NUMERIC 0 0 10 033213 1D VAR RADIANCE COST NUMERIC 1 -1000 11 033214 1D VAR ERROR(S) FLAG TABLE 33214 0 0 11 033215 DIRECTIONAL SKILL NUMERIC 1 -4096 13 033216 1D VAR SURFACE TYPE QUALITY CONTROL CODE TABLE 33216 0 0 3 033217 1D VAR FAILURE INDICATOR CODE TABLE 33217 0 0 2 033218 1D VAR ESTIMATE OF SCATTERING NUMERIC 2 0 12 033219 SSMI INDIPENDENT SCATTERING INDEX NUMERIC 2 -50000 16 033220 VARIATIONAL ANALYSIS REPORT EVENTS (1) FLAG TABLE 33220 0 0 31 033221 VARIATIONAL ANALYSIS SYNOP EVENTS (2) FLAG TABLE 33221 0 0 31 033222 VARIATIONAL ANALYSIS AIREP EVENTS (2) FLAG TABLE 33222 0 0 31 033223 VARIATIONAL ANALYSIS SATOB EVENTS (2) FLAG TABLE 33223 0 0 31 033224 VARIATIONAL ANALYSIS DRIBU EVENTS (2) FLAG TABLE 33224 0 0 31 033225 VARIATIONAL ANALYSIS TEMP EVENTS (2) FLAG TABLE 33225 0 0 31 033226 VARIATIONAL ANALYSIS PILOT EVENTS (2) FLAG TABLE 33226 0 0 31 033227 VARIATIONAL ANALYSIS SATEM/TOVS EVENTS (2) FLAG TABLE 33227 0 0 31 033228 VARIATIONAL ANALYSIS PAOB EVENTS (2) FLAG TABLE 33228 0 0 31 033229 VARIATIONAL ANALYSIS SCATTEROMETER EVENTS (2) FLAG TABLE 33229 0 0 31 033230 VARIATIONAL ANALYSIS RAW RADIANCES EVENTS (2) FLAG TABLE 33230 0 0 31 033231 PRESAT SUMMARY FLAGS FLAG TABLE 33231 0 0 6 033232 REPORT BLACK LIST EVENTS FLAG TABLE 33232 0 0 31 033233 VARIATIONAL ANALYSIS REPORT STATUS FLAG TABLE 33233 0 0 31 033234 VARIATIONAL ANALYSIS DATUM STATUS FLAG TABLE 33234 0 0 31 033236 VARIATIONAL ANALYSIS DATUM EVENTS (1) FLAG TABLE 33236 0 0 31 033237 VARIATIONAL ANALYSIS SYNOP DATUM EVENTS (2) FLAG TABLE 033237 0 0 31 033238 VARIATIONAL ANALYSIS AIREP DATUM EVENTS (2) FLAG TABLE 033238 0 0 31 033239 VARIATIONAL ANALYSIS SATOB DATUM EVENTS (2) FLAG TABLE 033239 0 0 31 033240 VARIATIONAL ANALYSIS DRIBU DATUM EVENTS (2) FLAG TABLE 033240 0 0 31 033241 GROSS ERROR PROBABILITY NUMERIC 3 0 10 033242 GROSS ERROR INDICATOR CODE TABLE 33242 0 0 2 033243 VARIATIONAL ANALYSIS TEMP DATUM EVENTS (2) FLAG TABLE 33243 0 0 31 033244 VARIATIONAL ANALYSIS PILOT DATUM EVENTS (2) FLAG TABLE 033244 0 0 31 033245 VARIATIONAL ANALYSIS SATEM/TOVS DATUM EVENTS (2) FLAG TABLE 33245 0 0 31 033246 VARIATIONAL ANALYSIS PAOB DATUM EVENTS (2) FLAG TABLE 33246 0 0 31 033247 VARIATIONAL ANALYSIS SCATTEROMETER DATUM EVENTS (2) FLAG TABLE 33247 0 0 31 033248 VARIATIONAL ANALYSIS RAW RADIANCES DATUM EVENTS (2) FLAG TABLE 33248 0 0 31 033249 DATUM BLACK LIST EVENTS FLAG TABLE 33249 0 0 31 033250 PROBABILITY OF GROSS ERROR NUMERIC 6 0 20 033251 RANGE OF POSSIBLE VALUES NUMERIC 2 0 14 033252 MANUAL-AUTOMATIC QUALITY CONTROL CODE TABLE 33252 0 0 4 033253 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 033254 WIND CORRELATION METHOD FLAG TABLE 33254 0 0 20 035000 FM AND REGIONAL CODE NUMBER CODE TABLE 035000 0 0 10 035001 TIME-FRAME FOR MONITORING CODE TABLE 035001 0 0 3 035011 NUMBER OF REPORTS ACTUALLY RECEIVED NUMERIC 0 0 14 035021 BULLETIN BEING MONITORED (TTAAII) CCITTIA5 0 0 48 035022 BULLETIN BEING MONITORED (YYGGGG) CCITTIA5 0 0 48 035023 BULLETIN BEING MONITORED (CCCC) CCITTIA5 0 0 32 035024 BULLETIN BEING MONITORED (BBB) CCITTIA5 0 0 24 035030 DISCREPANCIES IN THE AVAILABILITY OF EXPECTED DATA CODE TABLE 035030 0 0 4 035031 QUALIFIER ON MONITORING RESULTS CODE TABLE 035031 0 0 7 035032 CAUSE OF MISSING DATA CODE TABLE 035032 0 0 4 035033 OBSERVATION AND COLLECTION DEFICIENCIES CODE TABLE 035033 0 0 7 035034 STATISTICAL TRENDS FOR AVAILABILITY OF DATA (DURING THE SURVEY P CODE TABLE 035034 0 0 3 049193 SAR INVERSION QC FLAGS FLAG TABLE 49193 0 0 15 049194 ALTIMETER WAVE HEIGHT QC FLAFS FLAG TABLE 49194 0 0 15 062190 STATISTICS APPLICATION CODE TABLE 62190 0 0 8 062191 TYPE OF STATISTICS CODE TABLE 62191 0 0 8 063190 APPLICATION DERIVING SUBSTITUTE OR ALTERNATIVE VALUE CODE TABLE 63190 0 0 8 dballe-7.7/extra/aof/0000755000175000017500000000000012652630043011504 500000000000000dballe-7.7/extra/aof/err1.aof0000644000175000017500000000056412652630043012771 000000000000008 âg2Mÿÿÿ<ÿÿÿÿÿÿÿÿÿ8D4âg2Mÿÿÿÿÿÿ<S”°wS”°wÿÿÿÿÿÿÿÿÿDlÿÿÿÿÿÿÿÿÿôN6OGg@2ÜÁaÔ A©´ ÿÿÿÿÿÿéÿ‚ Ä$J ÿÿÿ‚ÿÿÿllÿÿÿÿÿÿÿÿÿôN6OGg@2ÜÁaÔ A©´ ÿÿÿÿÿÿéÿ‚ )$< ÿÿÿ‚ÿÿÿldballe-7.7/extra/aof/confship.aof0000644000175000017500000000044012652630043013722 000000000000008 ài2›ÿÿÿ<ÿÿÿÿÿÿÿÿÿ8Dài2›ÿÿÿÿÿÿ<0=¢w0=¢wÿÿÿÿÿÿÿÿÿDŒ#ÿÿÿÿÿÿÿÿÿJ8¾F,C2Îd3ز ÿÿÿèéÿ? ^(6 õ ÿÿÿÿÿÿÿÿÿÿÿÿ‚ÿ‡ÿÿÿŒdballe-7.7/extra/aof/aof_28-2-144.aof0000644000175000017500000000040412652630043013634 000000000000008 g2Iÿÿÿ<ÿÿÿÿÿÿÿÿÿ8D4g2Iÿÿÿÿÿÿ<Mt°wMt°wÿÿÿÿÿÿÿÿÿDpÿÿÿÿÿÿÿÿÿº7 Hg2„ªÕ"´ ÿÿÿÿÿÿéÿ€ m¹½ ® ÿÿÿ‚ÿÿÿpdballe-7.7/extra/aof/aof_28-2-244.aof0000644000175000017500000000040412652630043013635 000000000000008 g2Iÿÿÿ<ÿÿÿÿÿÿÿÿÿ8D4g2Iÿÿÿÿÿÿ<Mt°wMt°wÿÿÿÿÿÿÿÿÿDpÿÿÿÿÿÿÿÿÿô 8ªFg2„£C&1A)Lÿÿÿÿÿÿéÿ?‚ - Ï/êÿÿÿÿÿÿ‚ÿÿÿpdballe-7.7/extra/aof/obs5-36.30.aof0000644000175000017500000000364412652630043013441 000000000000008 1ôQúÿÿÿ<ÿÿÿÿÿÿÿÿÿ8D41ôQúÿÿÿÿÿÿÝBí1ͪ°°0,1ÿÿÿñ?ÿé ‚'82 › Uñ ‚'2 ¡  ‚%bFÿÿÿÿÿÿÿÿÿ $"< c 'v ‚#Œ7ÿÿÿÿÿÿÿÿÿ "ˆAÿÿÿÿÿÿÿÿÿ!ÀA ÿÿÿÿÿÿÿÿÿ !42 '   ‚ €# ÿÿÿÿÿÿÿÿÿ  & ÿÿÿÿÿÿÿÿÿ êÿÿÿÿÿÿ ù 0 ‚¤ÿÿÿÿÿÿ  Õ p ‚T# ÿÿÿÿÿÿÿÿÿ @# ÿÿÿÿÿÿÿÿÿªÿÿÿÿÿÿ  e ] ‚âÿÿÿÿÿÿÿÿÿ °ÿÿÿÿÿÿ _ Q ‚¨h ÿÿÿÿÿÿÿÿÿ X^ Ý µ ‚¸ÿÿÿÿÿÿ Í }a ‚Jÿÿÿÿÿÿ ë }Ø ‚;ÿÿÿÿÿÿÿÿÿ Œ,ÿÿÿÿÿÿÿÿÿ p1 ÿÿÿÿÿÿÿÿÿ>ÿÿÿÿÿÿ µ ec ‚r6 ÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿ / ‚ˆ' o E ‚f ÿÿÿÿÿÿÿÿÿ Šÿÿÿÿÿÿ -ý5 ‚  íÿÿÿJ Œ ÿÿÿÿÿÿÿÿÿ âÿÿÿÿÿÿÏÿÿÿˆ Äÿÿÿÿÿÿÿÿÿ jÿÿÿÿÿÿÁÿÿÿ [  ÿÿÿÿÿÿ¯ÿÿÿ"¿  ¸ —ÿÿÿ%¤  ¤ •ÿÿÿ%È"  P" ÿÿÿÿÿÿÿÿÿ  Ä •ÿÿÿ*7  t' ÿÿÿÿÿÿÿÿÿ 4ÿÿÿÿÿÿ£ÿÿÿ.›  " ÿÿÿÿÿÿÿÿÿ Ð ÿÿÿ/Ø v ÿÿÿÿÿÿÿÿÿ "' ÿÿÿÿÿÿÿÿÿ Ü' ÿÿÿ7 n ÿÿÿÿÿÿÿÿÿ èuÿÿÿA3 6 ÿÿÿÿÿÿÿÿÿB¼6 mÿÿÿIþ‚ S1 ÿÿÿÿÿÿÿÿÿBô; aÿÿÿRG‚ äÿÿÿÿÿÿcÿÿÿÿÿÿ@›1ÿÿÿÿÿÿÿÿÿBl@!ÿÿÿÿÿÿbTÿÿÿÿÿÿ3ÿÿÿÿÿÿ@SOÿÿÿÿÿÿÿÿÿB,O%ÿÿÿ^—‚  JÿÿÿÿÿÿÿÿÿBÝJÿÿÿÿÿÿÿÿÿBÈTÿÿÿÿh+‚ ¿Y÷ÿÿÿÿÿÿBÿÿÿ0dballe-7.7/extra/aof/obs6-32.1573.aof0000644000175000017500000000106412652630043013605 000000000000008 1ôQúÿÿÿ<ÿÿÿÿÿÿÿÿÿ8D41ôQúÿÿÿÿÿÿ–A A!ÀÒûê[Ìšf€Mˆë „Ñÿþ& ¬ ÿÿÄÁ‘8„ÿøÀs@ƒÿÿBîÿäBlNÀÿüˆR‰ÄAÿÿ‘ Pú?ÿñÑqÿþXÁô ÿÿȃ +ÄÿøèZèƒÿÿvÿÀP€ÌB„!B‚1€ F4hÑ£F\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ\hÑ¥Æ4hÑ£7777dballe-7.7/extra/aof/obs1-14.63.aof0000644000175000017500000000043012652630043013425 000000000000008 1ôQúÿÿÿ<ÿÿÿÿÿÿÿÿÿ8D41ôQúÿÿÿÿÿÿXMG1ͪ°°0,µÿÿÿö?ÿé  ‚ÿÿÿ  Õ ¬ÿÿÿÿÿÿÿÿÿÿÿÿH ‚APÿÿÿ„dballe-7.7/extra/aof/obs1-24.2104.bufr0000644000175000017500000000030612652630043013757 00000000000000BUFRÆb€   4 }Ky€G£Øeư61001 ÆyŽ@yŒ\F€È  Å–A" A"!X61001 ê[Ì âJçÿóº¾NÈ‹®ÿÿÿÿÿÁÿÿ÷¾Yÿÿ‚€ Ñ£F4hÖ­F6|hÒ¥F4hÑ£F—>|hÑ€7777dballe-7.7/extra/aof/obs2-144.2198.aof0000644000175000017500000000040012652630043013662 000000000000008 1ôQúÿÿÿ<ÿÿÿÿÿÿÿÿÿ8D41ôQúÿÿÿÿÿÿ2‰XÿÿÿÿÈÁ-! 1Ñ8ð(#Œÿÿÿÿÿ„´Q¿ÿÿÿÿä–‡ÿÿÿÿü‚š HQ=Œâ_ÿÿÿÿñ7@L ÿÿÿÿþçú‚î(.~ÿþý @?½ίÿÿßTÿÿÿÿÿ„è¿ÿÿÿÿâ0‚z¨ #~ƒå—ÿÿîñÿÿÿÿÿBùÛ€œê •ÿÿÿ·P ÿÿÿÿÿhæÖ §vckÀðÕÀ@ftæËïÿÿÚJ Cž¹}ÿÿûAÀ¿ÿÿÿÿó°Ff0ÿÿÿÿþX ¸ÿÿÿÿÿÌAisà ɵ–_ÿÿªä ÿÿÿÿÿ6…C‚ÞfvAÿÿþœB¬,·È œfÿÿÿÿÿ‡Ò1A Ò[¿ÿÿ>m®;þÆÿÿÿÿÿÂBî Ê8Ïÿÿÿÿˆ ÿÿÿÿÿ cš‚\cÿÿÿþi@þLWÿÿÿÿ˸@"Ÿ‰ÿŒqt…Xq+ÿñÐn)@ÿÿÿÿþD Dâ įÿÇA—@_ÿÿÿÿù87hVÑÿÿÿòÿÿÿÿä@´>‚düNÿüt‡vÿÿÿÿÿ‰ƒpÄ@¿ÿÿÿÿòp‚qÎÖ#þN·ÿÿÿÿÿƸ>„ÃÚuÿøèF ÿÿÿÿÿ6 ¯á·ÿæÀܘ/ÿÿÿÿüÄô@N^†ÿƒÀÿóœ¾NÈK®OãèZÿÿÁÿÿ÷¾ÿÿ‚€ Ñ£F4hÖ­F6|hÔ&ÆŸV4hÑ£F—>|hÑ€7777dballe-7.7/extra/aof/obs1-14.63.bufr0000644000175000017500000000033412652630043013621 00000000000000BUFRÜb€  4}Ky€KwVyÃà01015 Üy†¦y†F€Ç  –A1 A1!n©o0œ>[º°{ÿÿÿÿÿP%jÕgÿÿÿÿÿàÿÿûßÿÿø_ÿÿÿÿÿÿÿÿÿÿÿð hÑ£F4hÑ£F4iR£F4hÑ£KŸ>4hÑ£F4hÑ£F4`7777dballe-7.7/extra/aof/obs2-244.0.aof0000644000175000017500000000040012652630043013417 000000000000008 2ݼÿÿÿ<ÿÿÿÿÿÿÿÿÿ8D42ݼÿÿÿÿÿÿ‚g¼Lÿûü-Šÿÿÿÿÿ}@äÁãÑ[ÿÿÿÿÐÿÿÿÿþÃMŠÄ?ÿÿÿü]Ä@؉ÿø˜K ÿÿÿÿÿÁ$ÿÿÿÿå@#/ÿÿÿÿüœ „.ÿÿÿÿÿŒ°} ‡¼°Óÿò – ÜÿÿÿÿþDÿÿÿÿÿÉÂÐ.à_ÿÿÿÿùØP’‹Ïÿÿÿÿð¯™àïÿæÀðÈ/ÿÿÿÿüØKJ‚„ßÿÿÿøEà¿ÿÿÿÿô ŒÑ9¢ÿþŠ€æÿÿÿÿÿÍ‚¨`_ÿÿÿÿûnX€´|ÿ?ÿ^`Jžß×ÿÿÿþÀBô\ÿÿÿÿÀÈ@c—?ÿªÀA ï»ÿÿÿÿÄÿÿÿÿþ¨$@V†3a>ÏÿÕˆ=àÀ ÀÀ áà@çp8C‡páÀá8áÀÄp ÄhÑ£FbÄhÑ£F4¸Ñ£F4hÒãF”iQ£F.4hÑ¥Æ4¸Ñ£R*4hÑ¥Æ5(Ò£F\hÑ£K4iq£F.4hÑ©F•4hÒãFJ4¨Ñ£O4hÒãF>4hÑ£R*4hÒãFJ4¨Ñ£K4¸Ñ£R*4hÒãF.4hÒãF.4hÔ£J4¸Ñ£K4¸Ñ£K5(Ò£F.4hÒãF.4hÒãFJ4¨Ñ£K4¸Ñ£K5(Ò£F.4hÒãFJ4¨Ñ£K4¸Ñ£R*4hÒãF.4hÓãF07777dballe-7.7/extra/test-crex-table.txt0000644000175000017500000044750412652630043014441 00000000000000 000001 TABLE A: ENTRY CCITTIA5 0 0 24 CHARACTER 0 3 000002 TABLE A: DATA CATEGORY DESCRIPTION, LINE 1 CCITTIA5 0 0 256 CHARACTER 0 32 000003 TABLE A: DATA CATEGORY DESCRIPTION, LINE 2 CCITTIA5 0 0 256 CHARACTER 0 32 000005 BUFR/CREX EDITION NUMBER CCITTIA5 0 0 24 CHARACTER 0 3 000010 F DESCRIPTOR TO BE ADDED OR DEFINED CCITTIA5 0 0 8 CHARACTER 0 1 000011 X DESCRIPTOR TO BE ADDED OR DEFINED CCITTIA5 0 0 16 CHARACTER 0 2 000012 Y DESCRIPTOR TO BE ADDED OR DEFINED CCITTIA5 0 0 24 CHARACTER 0 3 000013 ELEMENT NAME, LINE 1 CCITTIA5 0 0 256 CHARACTER 0 32 000014 ELEMENT NAME, LINE 2 CCITTIA5 0 0 256 CHARACTER 0 32 000015 UNITS NAME CCITTIA5 0 0 192 CHARACTER 0 24 000016 UNITS SCALE SIGN CCITTIA5 0 0 8 CHARACTER 0 1 000017 UNITS SCALE CCITTIA5 0 0 24 CHARACTER 0 3 000018 UNITS REFERENCE SIGN CCITTIA5 0 0 8 CHARACTER 0 1 000019 UNITS REFERENCE VALUE CCITTIA5 0 0 80 CHARACTER 0 10 000020 ELEMENT DATA WIDTH CCITTIA5 0 0 24 CHARACTER 0 3 000030 DESCRIPTOR DEFINING SEQUENCE CCITTIA5 0 0 48 CHARACTER 0 6 001001 WMO BLOCK NUMBER NUMERIC 0 0 7 NUMERIC 0 2 001002 WMO STATION NUMBER NUMERIC 0 0 10 NUMERIC 0 3 001003 WMO REGION NUMBER/GEOGRAPHICAL AREA CODE TABLE 1003 0 0 3 CODE TABLE 1003 0 1 001004 WMO REGION SUB-AREA (SEE NOTE 9) NUMERIC 0 0 3 NUMERIC 0 1 001005 BUOY/PLATFORM IDENTIFIER NUMERIC 0 0 17 NUMERIC 0 5 001006 AIRCRAFT FLIGHT NUMBER CCITTIA5 0 0 64 CHARACTER 0 8 001007 SATELLITE IDENTIFIER CODE TABLE 1007 0 0 10 CODE TABLE 1007 0 4 001008 AIRCRAFT REGISTRATION NUMBER OR OTHER IDENTIFICATION CCITTIA5 0 0 64 CHARACTER 0 8 001009 TYPE OF COMMERCIAL AIRCRAFT CCITTIA5 0 0 64 CHARACTER 0 8 001010 STATIONARY BUOY PLATFORM IDENTIFIER; E.G. C-MAN BUOYS CCITTIA5 0 0 64 CHARACTER 0 8 001011 SHIP OR MOBILE LAND STATION IDENTIFIER CCITTIA5 0 0 72 CHARACTER 0 9 001012 DIRECTION OF MOTION OF MOVING OBSERVING PLATFORM** DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 001013 SPEED OF MOTION OF MOVING OBSERVING PLATFORM* M/S 0 0 10 M/S 0 3 001014 PLATFORM DRIFT SPEED (HIGH PRECISION) M/S 2 0 10 M/S 2 4 001015 STATION OR SITE NAME CCITTIA5 0 0 160 CHARACTER 0 20 001018 SHORT STATION OR SITE NAME CCITTIA5 0 0 40 CHARACTER 0 5 001019 LONG STATION OR SITE NAME CCITTIA5 0 0 256 CHARACTER 0 32 001020 WMO REGION SUB-AREA NUMERIC 0 0 4 NUMERIC 0 2 001021 SYNOPTIC FEATURE IDENTIFIER NUMERIC 0 0 14 NUMERIC 0 4 001022 NAME OF FEATURE (SEE NOTE 11) CCITTIA5 0 0 224 CHARACTER 0 28 001023 OBSERVATION SEQUENCE NUMBER NUMERIC 0 0 9 NUMERIC 0 3 001025 STORM IDENTIFIER CCITTIA5 0 0 24 CHARACTER 0 3 001026 WMO STORM NAME CCITTIA5 0 0 64 CHARACTER 0 8 001027 WMO LONG STORM NAME CCITTIA5 0 0 80 CHARACTER 0 10 001031 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE (SEE NOTE 10) CODE TABLE 1031 0 0 16 CODE TABLE 1031 0 5 001032 GENERATING APPLICATION CODE TABLE 1032 0 0 8 CODE TABLE 1032 0 3 001033 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE CODE TABLE 1022 0 0 8 CODE TABLE 1033 0 3 001034 IDENTIFICATION OF ORIGINATING/GENERATING SUB-CENTRE CODE TABLE 1034 0 0 8 CODE TABLE 1034 0 3 001035 ORIGINATING CENTRE CODE TABLE 1035 0 0 16 CODE TABLE 1035 0 5 001036 AGENCY IN CHARGE OF OPERATING THE OBSERVING PLATFORM CODE TABLE 1036 0 0 20 CODE TABLE 1036 0 7 001041 ABSOLUTE PLATFORM VELOCITY - FIRST COMPONENT (SEE NOTE 6) M/S 5 -1073741824 31 M/S 5 10 001042 ABSOLUTE PLATFORM VELOCITY - SECOND COMPONENT (SEE NOTE 6) M/S 5 -1073741824 31 M/S 5 10 001043 ABSOLUTE PLATFORM VELOCITY - THIRD COMPONENT (SEE NOTE 6) M/S 5 -1073741824 31 M/S 5 10 001050 PLATFORM TRANSMITTER ID NUMBER NUMERIC 0 0 17 NUMERIC 0 6 001051 PLATFORM TRANSMITTER ID NUMBER CCITTIA5 0 0 96 CHARACTER 0 12 001060 AIRCRAFT REPORTING POINT (BEACON IDENTIFIER) CCITTIA5 0 0 64 CHARACTER 0 8 001062 SHORT ICAO LOCATION INDICATOR CCITTIA5 0 0 32 CHARACTER 0 4 001063 ICAO LOCATION INDICATOR CCITTIA5 0 0 64 CHARACTER 0 8 001064 RUNWAY DESIGNATOR CCITTIA5 0 0 32 CHARACTER 0 4 001075 TIDE STATION IDENTIFICATION CCITTIA5 0 0 40 CHARACTER 0 5 001080 SHIP LINE NUMBER ACCORDING TO SOOP CCITTIA5 0 0 32 CHARACTER 0 4 001081 RADIOSONDE SERIAL NUMBER CCITTIA5 0 0 160 CHARACTER 0 20 001082 RADIOSONDE ASCENSION NUMBER (SEE NOTE 12) NUMERIC 0 0 14 NUMERIC 0 4 001083 RADIOSONDE RELEASE NUMBER (SEE NOTE 12) NUMERIC 0 0 3 NUMERIC 0 1 001085 OBSERVING PLATFORM MANUFACTURER'S MODEL CCITTIA5 0 0 160 CHARACTER 0 20 001086 OBSERVING PLATFORM MANUFACTURER'S SERIAL NUMBER CCITTIA5 0 0 256 CHARACTER 0 32 001090 TECHNIQUE FOR MAKING UP INITIAL PERTURBATIONS CODE TABLE 1090 0 0 8 CODE TABLE 1090 0 3 001091 ENSEMBLE MEMBER NUMBER NUMERIC 0 0 10 NUMERIC 0 4 001092 TYPE OF ENSEMBLE FORECAST CODE TABLE 1092 0 0 8 CODE TABLE 1092 0 3 001093 BALLOON LOT NUMBER CCITTIA5 0 0 96 CHARACTER 0 12 001094 WBAN NUMBER NUMERIC 0 0 17 NUMERIC 0 5 001095 OBSERVER IDENTIFICATION CCITTIA5 0 0 32 CHARACTER 0 4 001196 CONSTANT LEVEL BALLOON IDENTIFIER CCITTIA5 0 0 72 CHARACTER 0 9 001197 RTP - PLATFORM TYPE CODE TABLE 1197 0 0 10 CODE TABLE 0 4 001198 ITP - DECK ID CODE TABLE 1198 0 0 10 CODE TABLE 0 4 001199 DUP - DUPLICATE STATUS CODE TABLE 1199 0 0 4 CODE TABLE 0 2 001201 GENERATING APPLICATION CODE TABLE 1201 0 0 8 CODE TABLE 0 3 001205 SATELLITE IDENTIFIER CODE TABLE 1205 0 0 10 CODE TABLE 0 4 001208 VELOCITY OF PLATFORM, X M/S 5 -1073741824 31 M/S 5 10 001209 VELOCITY OF PLATFORM, Y M/S 5 -1073741824 31 M/S 5 10 001210 VELOCITY OF PLATFORM, Z M/S 5 -1073741824 31 M/S 5 10 002001 TYPE OF STATION CODE TABLE 2001 0 0 2 CODE TABLE 2001 0 1 002002 TYPE OF INSTRUMENTATION FOR WIND MEASUREMENT FLAG TABLE 2002 0 0 4 FLAG TABLE 2002 0 2 002003 TYPE OF MEASURING EQUIPMENT USED CODE TABLE 2003 0 0 4 CODE TABLE 2003 0 2 002004 TYPE OF INSTRUMENTATION FOR EVAPORATION MEASUREMENT OR TYPE OF C CODE TABLE 2004 0 0 4 CODE TABLE 2004 0 2 002005 PRECISION OF TEMPERATURE OBSERVATION K 2 0 7 K 2 3 002011 RADIOSONDE TYPE CODE TABLE 2011 0 0 8 CODE TABLE 2011 0 3 002012 RADIOSONDE COMPUTATIONAL METHOD CODE TABLE 2012 0 0 4 CODE TABLE 2012 0 2 002013 SOLAR AND INFRARED RADIATION CORRECTION CODE TABLE 2013 0 0 4 CODE TABLE 2013 0 2 002014 TRACKING TECHNIQUE/STATUS OF SYSTEM USED CODE TABLE 2014 0 0 7 CODE TABLE 2014 0 3 002015 RADIOSONDE COMPLETENESS CODE TABLE 2015 0 0 4 CODE TABLE 2015 0 2 002016 RADIOSONDE CONFIGURATION FLAG TABLE 2016 0 0 5 FLAG TABLE 2016 0 2 002019 SATELLITE INSTRUMENTS CODE TABLE 2019 0 0 11 CODE TABLE 2019 0 4 002020 SATELLITE CLASSIFICATION CODE TABLE 2020 0 0 9 CODE TABLE 2020 0 3 002021 SATELLITE INSTRUMENT DATA USED IN PROCESSING FLAG TABLE 2021 0 0 9 FLAG TABLE 2021 0 3 002022 SATELLITE DATA-PROCESSING TECHNIQUE USED FLAG TABLE 2022 0 0 8 FLAG TABLE 2022 0 3 002023 SATELLITE DERIVED WIND COMPUTATION METHOD CODE TABLE 2023 0 0 4 CODE TABLE 2023 0 2 002024 INTEGRATED MEAN HUMIDITY COMPUTATIONAL METHOD CODE TABLE 2024 0 0 4 CODE TABLE 2024 0 2 002025 SATELLITE CHANNEL(S) USED IN COMPUTATION FLAG TABLE 2025 0 0 25 FLAG TABLE 2025 0 9 002026 CROSS TRACK RESOLUTION M 2 0 12 M 2 4 002027 ALONG TRACK RESOLUTION M 2 0 12 M 2 4 002028 SEGMENT SIZE AT NADIR IN X DIRECTION M 0 0 18 M 0 6 002029 SEGMENT SIZE AT NADIR IN Y DIRECTION M 0 0 18 M 0 6 002030 METHOD OF CURRENT MEASUREMENT CODE TABLE 2030 0 0 3 CODE TABLE 2030 0 1 002031 DURATION AND TIME OF CURRENT MEASUREMENT CODE TABLE 2031 0 0 5 CODE TABLE 2031 0 2 002032 INDICATOR FOR DIGITIZATION CODE TABLE 2032 0 0 2 CODE TABLE 2032 0 1 002033 METHOD OF SALINITY/DEPTH MEASUREMENT CODE TABLE 2033 0 0 3 CODE TABLE 2033 0 1 002034 DROGUE TYPE CODE TABLE 2034 0 0 5 CODE TABLE 2034 0 2 002035 CABLE LENGTH M 0 0 9 M 0 3 002036 BUOY TYPE CODE TABLE 2036 0 0 2 CODE TABLE 2036 0 1 002037 METHOD OF TIDAL OBSERVATION CODE TABLE 2037 0 0 3 CODE TABLE 2037 0 1 002038 METHOD OF WATER TEMPERATURE AND/OR SALINITY MEASUREMENT CODE TABLE 2038 0 0 4 CODE TABLE 2038 0 2 002039 METHOD OF WET-BULB TEMPERATURE MEASUREMENT CODE TABLE 2039 0 0 3 CODE TABLE 2039 0 1 002040 METHOD OF REMOVING VELOCITY AND MOTION OF PLATFORM FROM CURRENT CODE TABLE 2040 0 0 4 CODE TABLE 2040 0 2 002041 METHOD FOR ESTIMATING REPORTS RELATED TO SYNOPTIC FEATURES CODE TABLE 2041 0 0 6 CODE TABLE 2041 0 2 002044 INDICATOR FOR METHOD OF CALCULATING SPECTRAL WAVE DATA CODE TABLE 2044 0 0 4 CODE TABLE 2044 0 2 002045 INDICATOR FOR TYPE OF PLATFORM CODE TABLE 2045 0 0 4 CODE TABLE 2045 0 2 002046 WAVE MEASUREMENT INSTRUMENTATION CODE TABLE 2046 0 0 4 CODE TABLE 2046 0 2 002048 SATELLITE SENSOR INDICATOR CODE TABLE 2048 0 0 4 CODE TABLE 2048 0 2 002049 GEOSTATIONARY SATELLITE DATA-PROCESSING TECHNIQUE USED FLAG TABLE 2049 0 0 8 FLAG TABLE 2049 0 3 002050 GEOSTATIONARY SOUNDER SATELLITE CHANNELS USED FLAG TABLE 2050 0 0 20 FLAG TABLE 2050 0 7 002051 INDICATOR TO SPECIFY OBSERVING METHOD FOR EXTREME TEMPERATURES CODE TABLE 2051 0 0 4 CODE TABLE 2051 0 2 002052 GEOSTATIONARY IMAGER SATELLITE CHANNELS USED FLAG TABLE 2052 0 0 6 FLAG TABLE 2052 0 2 002053 GOES-I/M BRIGHTNESS TEMPERATURE CHARACTERISTICS CODE TABLE 2053 0 0 4 CODE TABLE 2053 0 2 002054 GOES-I/M SOUNDINGS PARAMETER CHARACTERISTICS CODE TABLE 2054 0 0 4 CODE TABLE 2054 0 2 002055 GEOSTATIONARY SOUNDINGS STATISTICAL PARAMETERS CODE TABLE 2055 0 0 4 CODE TABLE 2055 0 2 002056 GEOSTATIONARY SOUNDINGS ACCURACY STATISTICS CODE TABLE 2056 0 0 4 CODE TABLE 2056 0 2 002057 ORIGIN OF FIRST GUESS INFORMATION FOR GOES-I/M SOUNDINGS CODE TABLE 2057 0 0 4 CODE TABLE 2057 0 2 002058 VALID TIMES OF FIRST GUESS INFORMATION FOR GOES-I/M SOUNDINGS CODE TABLE 2058 0 0 4 CODE TABLE 2058 0 2 002059 ORIGIN OF ANALYSIS INFORMATION FOR GOES-I/M SOUNDINGS CODE TABLE 2059 0 0 4 CODE TABLE 2059 0 2 002060 ORIGIN OF SURFACE INFORMATION FOR GOES-I/M SOUNDINGS CODE TABLE 2060 0 0 4 CODE TABLE 2060 0 2 002061 AIRCRAFT NAVIGATIONAL SYSTEM CODE TABLE 2061 0 0 3 CODE TABLE 2061 0 1 002062 TYPE OF AIRCRAFT DATA RELAY SYSTEM CODE TABLE 2062 0 0 4 CODE TABLE 2062 0 2 002063 AIRCRAFT ROLL ANGLE DEGREE 2 -18000 16 DEGREE 2 5 002064 AIRCRAFT ROLL ANGLE QUALITY CODE TABLE 2064 0 0 2 CODE TABLE 2064 0 1 002065 ACARS GROUND RECEIVING STATION CCITTIA5 0 0 40 CHARACTER 0 5 002066 RADIOSONDE GROUND RECEIVING SYSTEM CODE TABLE 2066 0 0 6 CODE TABLE 2066 0 2 002067 RADIOSONDE OPERATING FREQUENCY Hz -5 0 15 Hz -5 5 002070 ORIGINAL SPECIFICATION OF LATITUDE/LONGITUDE CODE TABLE 2070 0 0 4 CODE TABLE 2070 0 2 002080 BALLOON MANUFACTURER CODE TABLE 2080 0 0 6 CODE TABLE 2080 0 2 002081 TYPE OF BALLOON CODE TABLE 2081 0 0 5 CODE TABLE 2081 0 2 002082 WEIGHT OF BALLOON KG 3 0 12 KG 3 4 002083 TYPE OF BALLOON SHELTER CODE TABLE 2083 0 0 4 CODE TABLE 2083 0 2 002084 TYPE OF GAS USED IN BALLOON CODE TABLE 2084 0 0 4 CODE TABLE 2084 0 2 002085 AMOUNT OF GAS USED IN BALLOON KG 3 0 13 KG 3 4 002086 BALLOON FLIGHT TRAIN LENGTH M 1 0 10 M 1 4 002091 ENTRY SENSOR 4/20 MA A 4 0 10 A 4 3 002095 TYPE OF PRESSURE SENSOR CODE TABLE 2095 0 0 5 CODE TABLE 2095 0 2 002096 TYPE OF TEMPERATURE SENSOR CODE TABLE 2096 0 0 5 CODE TABLE 2096 0 2 002097 TYPE OF HUMIDITY SENSOR CODE TABLE 2097 0 0 5 CODE TABLE 2097 0 2 002100 RADAR CONSTANT dB 1 0 12 dB 1 4 002101 TYPE OF ANTENNA CODE TABLE 2101 0 0 4 CODE TABLE 2101 0 2 002102 ANTENNA HEIGHT ABOVE TOWER BASE M 0 0 8 M 0 3 002103 RADOME FLAG TABLE 2103 0 0 2 FLAG TABLE 2103 0 1 002104 ANTENNA POLARISATION CODE TABLE 2104 0 0 4 CODE TABLE 2104 0 2 002105 MAXIMUM ANTENNA GAIN dB 0 0 6 dB 0 2 002106 3-DB BEAMWIDTH DEGREE 1 0 6 DEGREE 1 2 002107 SIDELOBE SUPPRESSION dB 0 0 6 dB 0 2 002108 CROSSPOL DISCRIMINATION (ON AXIS) dB 0 0 6 dB 0 2 002109 ANTENNA SPEED (AZIMUTH) DEGREE/S 2 0 12 DEGREE/S 2 4 002110 ANTENNA SPEED (ELEVATION) DEGREE/S 2 0 12 DEGREE/S 2 4 002111 RADAR INCIDENCE ANGLE DEGREE 1 0 10 DEGREE 1 4 002112 RADAR LOOK ANGLE DEGREE 1 0 12 DEGREE 1 4 002113 NUMBER OF AZIMUTH LOOKS NUMERIC 0 0 4 NUMERIC 0 2 002114 ANTENNA EFFECTIVE SURFACE AREA M**2 0 0 15 M**2 0 5 002115 TYPE OF SURFACE OBSERVING EQUIPMENT CODE TABLE 2115 0 0 5 CODE TABLE 2115 0 2 002121 MEAN FREQUENCY Hz -8 0 7 Hz -8 3 002122 FREQUENCY AGILITY RANGE Hz -6 -128 8 Hz -6 3 002123 PEAK POWER W -4 0 7 W -4 3 002124 AVERAGE POWER W -1 0 7 W -1 3 002125 PULSE REPETITION FREQUENCY Hz -1 0 8 Hz -1 3 002126 PULSE WIDTH S 7 0 6 S 7 2 002127 RECEIVER INTERMEDIATE FREQUENCY Hz -6 0 7 Hz -6 3 002128 INTERMEDIATE FREQUENCY BANDWIDTH Hz -5 0 6 Hz -5 2 002129 MINIMUM DETECTABLE SIGNAL dB 0 -150 5 dB 0 3 002130 DYNAMIC RANGE dB 0 0 7 dB 0 3 002131 SENSITIVITY TIME CONTROL (STC) FLAG TABLE 2131 0 0 2 FLAG TABLE 2131 0 1 002132 AZIMUTH POINTING ACCURACY DEGREE 2 0 6 DEGREE 2 2 002133 ELEVATION POINTING ACCURACY DEGREE 2 0 6 DEGREE 2 2 002134 ANTENNA BEAM AZIMUTH DEGREE 2 0 16 DEGREE 2 5 002135 ANTENNA ELEVATION DEGREE 2 -9000 15 DEGREE 2 5 002136 RANGE PROCESSED BY RANGE ATTENUATION CORRECTION M -3 0 16 M -3 5 002140 SATELLITE RADAR BEAM AZIMUTH ANGLE DEGREE 0 0 9 DEGREE 0 3 002141 MEASUREMENT TYPE CCITTIA5 0 0 24 CHARACTER 0 3 002142 OZONE INSTRUMENT SERIAL NUMBER/ IDENTIFICATION CCITTIA5 0 0 32 CHARACTER 0 4 002143 OZONE INSTRUMENT TYPE CODE TABLE 2143 0 0 7 CODE TABLE 2143 0 3 002144 LIGHT SOURCE TYPE FOR BREWER SPECTRO PHOTOMETER CODE TABLE 2144 0 0 4 CODE TABLE 2144 0 2 002145 WAVE LENGTH SETTING FOR DOBSON INSTRUMENTS CODE TABLE 2145 0 0 4 CODE TABLE 2145 0 2 002146 SOURCE CONDITIONS FOR DOBSON INSTRUMENTS CODE TABLE 2146 0 0 4 CODE TABLE 2146 0 2 002148 DATA COLLECTION AND/OR LOCATION SYSTEM CODE TABLE 2148 0 0 5 CODE TABLE 2148 0 2 002149 TYPE OF DATA BUOY CODE TABLE 2149 0 0 6 CODE TABLE 2149 0 2 002150 TOVS/ATOVS/AVHRR INSTRUMENTATION CHANNEL NUMBER CODE TABLE 2150 0 0 6 CODE TABLE 2150 0 2 002151 RADIOMETER IDENTIFIER CODE TABLE 2151 0 0 11 CODE TABLE 2151 0 4 002152 SATELLITE INSTRUMENT USED IN DATA PROCESSING(6) FLAG TABLE 2152 0 0 31 FLAG TABLE 2152 0 10 002153 SATELLITE CHANNEL CENTRE FREQUENCY Hz -8 0 26 Hz -8 8 002154 SATELLITE CHANNEL BAND WIDTH Hz -8 0 26 Hz -8 8 002163 HEIGHT ASSIGNMENT METHOD CODE TABLE 2163 0 0 4 CODE TABLE 2163 0 2 002164 TRACER CORRELATION METHOD CODE TABLE 2164 0 0 3 CODE TABLE 2164 0 1 002166 RADIANCE TYPE CODE TABLE 2166 0 0 4 CODE TABLE 2166 0 2 002167 RADIANCE COMPUTATIONAL METHOD CODE TABLE 2167 0 0 4 CODE TABLE 2167 0 2 002168 HYDROSTATIC PRESSURE OF LOWER END OF CABLE (THERMISTOR STRING) PA -3 0 16 KPA 0 5 002169 ANEMOMETER TYPE CODE TABLE 2169 0 0 4 CODE TABLE 2169 0 2 002172 PRODUCT TYPE FOR RETRIEVED ATMOSPHERIC GASES CODE TABLE 2172 0 0 8 CODE TABLE 2172 0 3 002173 SQUARE OF THE OFF NADIR ANGLE (7) DEGREE2 4 0 10 DEGREE2 4 4 002175 METHOD OF PRECIPITATION MEASUREMENT CODE TABLE 2175 0 0 4 CODE TABLE 2175 0 2 002176 METHOD OF STATE OF GROUND MEASUREMENT CODE TABLE 2176 0 0 4 CODE TABLE 2176 0 2 002177 METHOD OF SNOW DEPTH MEASUREMENT CODE TABLE 2177 0 0 4 CODE TABLE 2177 0 2 002178 METHOD OF LIQUID CONTENT MEASUREMENT OF PRECIPITATION CODE TABLE 2178 0 0 4 CODE TABLE 2178 0 2 002179 TYPE OF SKY CONDITION ALGORITHM CODE TABLE 2179 0 0 4 CODE TABLE 2179 0 2 002180 MAIN PRESENT WEATHER DETECTING SYSTEM CODE TABLE 2180 0 0 4 CODE TABLE 2180 0 2 002181 SUPPLEMENTARY PRESENT WEATHER SENSOR FLAG TABLE 2181 0 0 21 FLAG TABLE 2181 0 7 002182 VISIBILITY MEASUREMENT SYSTEM CODE TABLE 2182 0 0 4 CODE TABLE 2182 0 2 002183 CLOUD DETECTION SYSTEM CODE TABLE 2183 0 0 4 CODE TABLE 2183 0 2 002184 TYPE OF LIGHTNING DETECTION SENSOR CODE TABLE 2184 0 0 4 CODE TABLE 2184 0 2 002185 METHOD OF EVAPORATION MEASUREMENT CODE TABLE 2185 0 0 4 CODE TABLE 2185 0 2 002186 CAPABILITY TO DETECT PRECIPITATION PHENOMENA FLAG TABLE 2186 0 0 30 FLAG TABLE 2186 0 10 002187 CAPABILITY TO DETECT OTHER WEATHER PHENOMENA FLAG TABLE 2187 0 0 18 FLAG TABLE 2187 0 6 002188 CAPABILITY TO DETECT OBSCURATION FLAG TABLE 2188 0 0 21 FLAG TABLE 2188 0 7 002189 CAPABILITY TO DISCRIMINATE LIGHTNING STRIKES FLAG TABLE 2189 0 0 12 FLAG TABLE 2189 0 4 002190 LAGRANGIAN DRIFTER SUBMERGENCE (% TIME SUBMERGED) % 0 0 7 % 0 3 002196 SATELLITE CLASSIFICATION CODE TABLE 2196 0 0 9 CODE TABLE 0 3 002197 SATELLITE CHANNEL CENTRE FREQUENCY Hz -8 0 26 Hz -8 8 002198 SATELLITE CHANNEL BAND WIDTH Hz -8 0 26 Hz -8 8 002199 INTEGRATED MEAN HUMIDITY COMPUTATIONAL METHOD CODE TABLE 2199 0 0 4 CODE TABLE 0 2 002221 SEGMENT SIZE AT NADIR IN X DIRECTION M 0 0 18 M 0 6 002222 SEGMENT SIZE AT NADIR IN Y DIRECTION M 0 0 18 M 0 6 002231 HEIGHT ASSIGNMENT METHOD CODE TABLE 2231 0 0 4 CODE TABLE 0 2 002232 TRACER CORRELATION METHOD CODE TABLE 2232 0 0 3 CODE TABLE 0 1 002251 RADIANCE COMPUTATIONAL METHOD CODE TABLE 2251 0 0 4 CODE TABLE 0 2 002252 SATELLITE INSTRUMENT DATA USED IN PROCESSING FLAG TABLE 2252 0 0 31 FLAG TABLE 0 10 002253 HUMIDITY COMPUTATIONAL METHOD CODE TABLE 2253 0 0 8 CODE TABLE 0 3 002254 RADIANCE TYPE CODE TABLE 2254 0 0 4 CODE TABLE 0 2 004001 YEAR YEAR 0 0 12 YEAR 0 4 004002 MONTH MONTH 0 0 4 MONTH 0 2 004003 DAY DAY 0 0 6 DAY 0 2 004004 HOUR HOUR 0 0 5 HOUR 0 2 004005 MINUTE MINUTE 0 0 6 MINUTE 0 2 004006 SECOND SECOND 0 0 6 SECOND 0 2 004007 SECONDS WITHIN A MINUTE (MICROSECOND ACCURACY) SECOND 6 0 26 SECOND 6 8 004011 TIME INCREMENT YEAR 0 -1024 11 YEAR 0 4 004012 TIME INCREMENT MONTH 0 -1024 11 MONTH 0 4 004013 TIME INCREMENT DAY 0 -1024 11 DAY 0 4 004014 TIME INCREMENT HOUR 0 -1024 11 HOUR 0 4 004015 TIME INCREMENT MINUTE 0 -2048 12 MINUTE 0 4 004016 TIME INCREMENT SECOND 0 -4096 13 SECOND 0 4 004017 REFERENCE TIME PERIOD FOR ACCUMULATED OR EXTREME DATA MINUTE 0 -1440 12 MINUTE 0 4 004021 TIME PERIOD OR DISPLACEMENT YEAR 0 -1024 11 YEAR 0 4 004022 TIME PERIOD OR DISPLACEMENT MONTH 0 -1024 11 MONTH 0 4 004023 TIME PERIOD OR DISPLACEMENT DAY 0 -1024 11 DAY 0 4 004024 TIME PERIOD OR DISPLACEMENT HOUR 0 -2048 12 HOUR 0 4 004025 TIME PERIOD OR DISPLACEMENT MINUTE 0 -2048 12 MINUTE 0 4 004026 TIME PERIOD OR DISPLACEMENT SECOND 0 -4096 13 SECOND 0 4 004031 DURATION OF TIME RELATING TO FOLLOWING VALUE HOUR 0 0 8 HOUR 0 3 004032 DURATION OF TIME RELATING TO FOLLOWING VALUE MINUTE 0 0 6 MINUTE 0 2 004041 TIME DIFFERENCE, UTC -LMT (SEE NOTE 6) MINUTE 0 -1440 12 MINUTE 0 4 004043 DAY OF THE YEAR DAY 0 0 9 DAY 0 3 004051 PRINCIPAL TIME OF DAILY READING OF MAXIMUM TEMPERATURE HOUR 0 0 5 HOUR 0 2 004052 PRINCIPAL TIME OF DAILY READING OF MINIMUM TEMPERATURE HOUR 0 0 5 HOUR 0 2 004053 NUMBER OF DAYS WITH PRECIPITATION EQUAL TO OR MORE THAN 1 MM NUMERIC 0 0 6 NUMERIC 0 2 004059 TIMES OF OBSERVATION USED TO COMPUTE THE REPORTED MEAN VALUES FLAG TABLE 4059 0 0 6 FLAG TABLE 4059 0 2 004065 SHORT TIME INCREMENT MINUTE 0 -128 8 MINUTE 0 2 004073 SHORT TIME PERIOD OR DISPLACEMENT DAY 0 -128 8 DAY 0 2 004074 SHORT TIME PERIOD OR DISPLACEMENT HOUR 0 -128 8 HOUR 0 2 004075 SHORT TIME PERIOD OR DISPLACEMENT MINUTE 0 -128 8 MINUTE 0 2 005001 LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 005002 LATITUDE (COARSE ACCURACY) DEGREE 2 -9000 15 DEGREE 2 4 005011 LATITUDE INCREMENT (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 005012 LATITUDE INCREMENT (COARSE ACCURACY) DEGREE 2 -9000 15 DEGREE 2 4 005021 BEARING OR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005022 SOLAR AZIMUTH DEGREE TRUE 2 0 16 DEGREE TRUE 2 5 005030 DIRECTION (SPECTRAL) DEGREE 0 0 12 DEGREE 0 4 005031 ROW NUMBER NUMERIC 0 0 12 NUMERIC 0 4 005033 PIXEL SIZE ON HORIZONTAL - 1 M -1 0 16 M -1 5 005034 ALONG TRACK ROW NUMBER NUMERIC 0 0 11 NUMERIC 0 4 005036 SHIP TRANSECT NUMBER ACCORDING TO SOOP NUMERIC 0 0 7 NUMERIC 0 2 005040 ORBIT NUMBER NUMERIC 0 0 24 NUMERIC 0 8 005041 SCAN LINE NUMBER NUMERIC 0 0 8 NUMERIC 0 3 005042 CHANNEL NUMBER NUMERIC 0 0 6 NUMERIC 0 2 005043 FIELD OF VIEW NUMBER NUMERIC 0 0 8 NUMERIC 0 3 005044 SATELLITE CYCLE NUMBER NUMERIC 0 0 11 NUMERIC 0 4 005052 CHANNEL NUMBER INCREMENT NUMERIC 0 0 5 NUMERIC 0 2 005053 FIELD OF VIEW NUMBER INCREMENT NUMERIC 0 0 5 NUMERIC 0 2 006001 LONGITUDE (HIGH ACCURACY) DEGREE 5 -18000000 26 DEGREE 5 8 006002 LONGITUDE (COARSE ACCURACY) DEGREE 2 -18000 16 DEGREE 2 5 006011 LONGITUDE INCREMENT (HIGH ACCURACY) DEGREE 5 -18000000 26 DEGREE 5 8 006012 LONGITUDE INCREMENT (COARSE ACCURACY) DEGREE 2 -18000 16 DEGREE 2 5 006021 DISTANCE M -1 0 13 M -1 4 006030 WAVE NUMBER (SPECTRAL) RAD/M 5 0 13 RAD/M 5 4 006031 COLUMN NUMBER NUMERIC 0 0 12 NUMERIC 0 4 006033 PIXEL SIZE ON HORIZONTAL - 2 M -1 0 16 M -1 5 006034 CROSS-TRACK CELL NUMBER NUMERIC 0 0 7 NUMERIC 0 3 006040 RADIUS OF CONFIDENCE M 0 0 13 M 0 4 007001 HEIGHT OF STATION (SEE NOTE 1) M 0 -400 15 M 0 5 007002 HEIGHT OR ALTITUDE M -1 -40 16 M -1 5 007003 GEOPOTENTIAL M**2/S**2 -1 -400 17 M**2/S**2 -1 6 007004 PRESSURE PA -1 0 14 PA -1 5 007005 HEIGHT INCREMENT M 0 -400 12 M 0 4 007006 HEIGHT ABOVE STATION M 0 0 15 M 0 5 007007 HEIGHT M 0 -1000 17 M 0 6 007008 GEOPOTENTIAL M**2/S**2 0 -10000 20 M**2/S**2 0 7 007009 GEOPOTENTIAL HEIGHT GPM 0 -1000 17 GPM 0 5 007010 FLIGHT LEVEL M 0 -1024 16 FT -1 5 007021 ELEVATION (SEE NOTE 2) DEGREE 2 -9000 15 DEGREE 2 5 007022 SOLAR ELEVATION DEGREE 2 -9000 15 DEGREE 2 5 007024 SATELLITE ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007025 SOLAR ZENITH ANGLE DEGREE 2 -9000 15 DEGREE 2 5 007030 HEIGHT OF STATION GROUND ABOVE MEAN SEA LEVEL (SEE NOTE 3) M 1 - 4000 17 M 1 5 007031 HEIGHT OF BAROMETER ABOVE MEAN SEA LEVEL (SEE NOTE 4) M 1 - 4000 17 M 1 5 007032 HEIGHT OF SENSOR ABOVE LOCAL GROUND (OR DECK OF MARINE PLATFORM) M 2 0 16 M 2 5 007033 HEIGHT OF SENSOR ABOVE WATER SURFACE (SEE NOTE 6) M 1 0 12 M 1 4 007061 DEPTH BELOW LAND SURFACE M 2 0 14 M 2 5 007062 DEPTH BELOW SEA/WATER SURFACE M 1 0 17 M 1 6 007064 HEIGHT ABOVE STATION (SENSOR HEIGHT ARTIFICIALLY CORRECTED) (SEE M 0 0 4 M 0 2 007070 DROGUE DEPTH M 0 0 10 M 0 4 008001 VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8001 0 0 7 FLAG TABLE 8001 0 3 008002 VERTICAL SIGNIFICANCE (SURFACE OBSERVATIONS) CODE TABLE 8002 0 0 6 CODE TABLE 8002 0 2 008003 VERTICAL SIGNIFICANCE (SATELLITE OBSERVATIONS) CODE TABLE 8003 0 0 6 CODE TABLE 8003 0 2 008004 PHASE OF AIRCRAFT FLIGHT CODE TABLE 8004 0 0 3 CODE TABLE 8004 0 1 008005 METEOROLOGICAL ATTRIBUTE SIGNIFICANCE CODE TABLE 8005 0 0 4 CODE TABLE 8005 0 2 008006 OZONE VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8006 0 0 9 FLAG TABLE 8006 0 3 008007 DIMENSIONAL SIGNIFICANCE CODE TABLE 8007 0 0 4 CODE TABLE 8007 0 2 008008 RADIATION VERTICAL SOUNDING SIGNIFICANCE FLAG TABLE 8008 0 0 9 FLAG TABLE 8008 0 3 008009 DETAILED PHASE OF FLIGHT CODE TABLE 8009 0 0 4 CODE TABLE 8009 0 2 008010 SURFACE QUALIFIER (TEMPERATURE DATA) CODE TABLE 8010 0 0 5 CODE TABLE 8010 0 2 008011 METEOROLOGICAL FEATURE CODE TABLE 8011 0 0 6 CODE TABLE 8011 0 2 008012 LAND/SEA QUALIFIER CODE TABLE 8012 0 0 2 CODE TABLE 8012 0 1 008013 DAY/NIGHT QUALIFIER CODE TABLE 8013 0 0 2 CODE TABLE 8013 0 1 008014 QUALIFIER FOR RUNWAY VISUAL RANGE CODE TABLE 8014 0 0 4 CODE TABLE 8014 0 2 008016 CHANGE QUALIFIER OF A TREND-TYPE FORECAST OR AN AERODROME FORECA CODE TABLE 8016 0 0 3 CODE TABLE 8016 0 1 008017 QUALIFIER OF THE TIME WHEN THE FORECAST CHANGE IS EXPECTED CODE TABLE 8017 0 0 2 CODE TABLE 8017 0 1 008018 SEAWINDS LAND/ICE SURFACE TYPE FLAG TABLE 8018 0 0 17 FLAG TABLE 8018 0 6 008020 TOTAL NUMBER OF MISSING ENTITIES (WITH RESPECT TO ACCUMULATION O NUMERIC 0 0 16 NUMERIC 0 5 008021 TIME SIGNIFICANCE CODE TABLE 8021 0 0 5 CODE TABLE 8021 0 2 008022 TOTAL NUMBER (WITH RESPECT TO ACCUMULATION OR AVERAGE) NUMERIC 0 0 16 NUMERIC 0 5 008023 FIRST ORDER STATISTICS CODE TABLE 8023 0 0 6 CODE TABLE 8023 0 2 008024 DIFFERENCE STATISTICS CODE TABLE 8024 0 0 6 CODE TABLE 8024 0 2 008025 TIME DIFFERENCE QUALIFIER CODE TABLE 8025 0 0 4 CODE TABLE 8025 0 2 008030 MANUAL ON CODES (VOLUME I.1, SECTION C) CODE TABLE FROM WHICH DA NUMERIC 0 0 13 NUMERIC 0 4 008031 DATA CATEGORY CREX TABLE A NUMERIC 0 0 8 NUMERIC 0 3 008033 METHOD OF DERIVATION OF PERCENTAGE CONFIDENCE CODE TABLE 8033 0 0 7 CODE TABLE 8033 0 3 008035 TYPE OF MONITORING EXERCISE CODE TABLE 8035 0 0 3 CODE TABLE 8035 0 1 008036 TYPE OF CENTRE OR STATION PERFORMING MONITORING CODE TABLE 8036 0 0 3 CODE TABLE 8036 0 1 008040 FLIGHT LEVEL SIGNIFICANCE CODE TABLE 8040 0 0 6 CODE TABLE 8040 0 2 008041 DATA SIGNIFICANCE CODE TABLE 8041 0 0 5 CODE TABLE 8041 0 2 008050 QUALIFIER FOR NUMBER OF MISSING VALUES IN CALCULATION OF STATIST CODE TABLE 8050 0 0 4 CODE TABLE 8050 0 2 008051 QUALIFIER FOR NUMBER OF MISSING VALUES IN CALCULATION OF STATIST CODE TABLE 8051 0 0 3 CODE TABLE 8051 0 1 008052 CONDITION FOR WHICH NUMBER OF DAYS OF OCCURRENCE FOLLOWS CODE TABLE 8052 0 0 5 CODE TABLE 8052 0 2 008053 DAY OF OCCURRENCE QUALIFIER CODE TABLE 8053 0 0 2 CODE TABLE 8053 0 1 008060 SAMPLE SCANNING MODE SIGNIFICANCE CODE TABLE 8060 0 0 4 CODE TABLE 8060 0 2 008070 TOVS/ATOVS PRODUCT QUALIFIER CODE TABLE 8070 0 0 4 CODE TABLE 8070 0 2 008072 PIXEL(S) TYPE CODE TABLE 8072 0 0 3 CODE TABLE 8072 0 1 008074 ALTIMETER ECHO TYPE CODE TABLE 8074 0 0 2 CODE TABLE 8074 0 1 008075 ASCENDING/DESCENDING ORBIT QUALIFIER CODE TABLE 8075 0 0 2 CODE TABLE 8075 0 1 008076 TYPE OF BAND CODE TABLE 8076 0 0 6 CODE TABLE 8076 0 2 008080 QUALIFIER FOR GTSSPP QUALITY FLAG CODE TABLE 8080 0 0 6 CODE TABLE 8080 0 2 008081 TYPE OF EQUIPMENT CODE TABLE 8081 0 0 6 CODE TABLE 8081 0 2 008082 ARTIFICIAL CORRECTION OF SENSOR HEIGHT TO ANOTHER VALUE CODE TABLE 8082 0 0 3 CODE TABLE 8082 0 1 010001 HEIGHT OF LAND SURFACE M 0 -400 15 M 0 5 010002 HEIGHT M -1 -40 16 M -1 5 010003 GEOPOTENTIAL M**2/S**2 -1 -400 17 M**2/S**2 -1 6 010004 PRESSURE PA -1 0 14 PA -1 5 010007 HEIGHT M 0 -1000 17 M 0 6 010008 GEOPOTENTIAL M**2/S**2 0 -10000 20 M**2/S**2 0 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 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 010051 PRESSURE REDUCED TO MEAN SEA LEVEL PA -1 0 14 PA -1 5 010052 ALTIMETER SETTING (QNH) PA -1 0 14 PA -1 5 010060 PRESSURE CHANGE PA -1 -1024 11 PA -1 4 010061 3-HOUR PRESSURE CHANGE PA -1 -500 10 PA -1 4 010062 24-HOUR PRESSURE CHANGE PA -1 -1000 11 PA -1 4 010063 CHARACTERISTIC OF PRESSURE TENDENCY CODE TABLE 10063 0 0 4 CODE TABLE 10063 0 2 010070 INDICATED AIRCRAFT ALTITUDE M 0 -400 16 M 0 5 010197 ANEMOMETER HEIGHT M 0 0 9 M 0 3 011001 WIND DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011002 WIND SPEED M/S 1 0 12 M/S 1 4 011003 U-COMPONENT M/S 1 -4096 13 M/S 1 4 011004 V-COMPONENT M/S 1 -4096 13 M/S 1 4 011005 W-COMPONENT PA/S 1 -512 10 PA/S 1 4 011006 W-COMPONENT M/S 2 -4096 13 M/S 2 4 011010 WIND DIRECTION ASSOCIATED WITH WIND SPEED WHICH FOLLOWS DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011011 WIND DIRECTION AT 10 M DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011012 WIND SPEED AT 10 M M/S 1 0 12 M/S 1 4 011013 WIND DIRECTION AT 5 M DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011014 WIND SPEED AT 5 M M/S 1 0 12 M/S 1 4 011016 EXTREME COUNTERCLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011017 EXTREME CLOCKWISE WIND DIRECTION OF A VARIABLE WIND DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011019 STEADINESS OF WIND (6) % 0 0 7 % 0 3 011021 RELATIVE VORTICITY 1/S 9 -65536 17 1/S 9 6 011022 DIVERGENCE 1/S 9 -65536 17 1/S 9 6 011023 VELOCITY POTENTIAL M**2/S -2 -65536 17 M**2/S -2 6 011031 DEGREE OF TURBULENCE CODE TABLE 11031 0 0 4 CODE TABLE 11031 0 2 011032 HEIGHT OF BASE OF TURBULENCE M -1 -40 16 M -1 5 011033 HEIGHT OF TOP OF TURBULENCE M -1 -40 16 M -1 5 011034 VERTICAL GUST VELOCITY M/S 1 -1024 11 M/S 1 4 011035 VERTICAL GUST ACCELERATION M/S**2 2 -8192 14 M/S**2 2 5 011036 MAXIMUM DERIVED EQUIVALENT VERTICAL GUST SPEED M/S 1 0 10 M/S 1 4 011037 TURBULENCE INDEX CODE TABLE 11037 0 0 6 CODE TABLE 11037 0 2 011038 TIME OF OCCURRENCE OF PEAK EDDY DISSIPATION RATE CODE TABLE 11038 0 0 5 CODE TABLE 11038 0 2 011039 EXTENDED TIME OF OCCURRENCE OF PEAK EDDY DISSIPATION RATE CODE TABLE 11039 0 0 6 CODE TABLE 11039 0 2 011040 MAXIMUM WIND SPEED (MEAN WIND) M/S 1 0 12 M/S 1 4 011041 MAXIMUM WIND GUST SPEED M/S 1 0 12 M/S 1 4 011042 MAXIMUM WIND SPEED (10-MIN MEAN WIND) M/S 1 0 12 M/S 1 4 011043 MAXIMUM WIND GUST DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011044 MEAN WIND DIRECTION FOR SURFACE - 1500 M (5000 FEET) DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011045 MEAN WIND SPEED FOR SURFACE - 1500 M (5000 FEET) M/S 1 0 12 M/S 1 4 011046 MAXIMUM INSTANTANEOUS WIND SPEED M/S 1 0 12 M/S 1 4 011047 MAXIMUM INSTANTANEOUS WIND SPEED OVER 10 MINUTES M/S 1 0 12 M/S 1 4 011049 STANDARD DEVIATION OF WIND DIRECTION DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 011050 STANDARD DEVIATION OF HORIZONTAL WIND SPEED M/S 1 0 12 M/S 1 4 011051 STANDARD DEVIATION OF VERTICAL WIND SPEED M/S 1 0 8 M/S 1 3 011052 FORMAL UNCERTAINTY IN WIND SPEED M/S 2 0 13 M/S 2 5 011053 FORMAL UNCERTAINTY IN WIND DIRECTION DEGREE TRUE 2 0 15 DEGREE TRUE 2 5 011061 ABSOLUTE WIND SHEAR IN 1 KM LAYER BELOW M/S 1 0 12 M/S 1 4 011062 ABSOLUTE WIND SHEAR IN 1 KM LAYER ABOVE M/S 1 0 12 M/S 1 4 011070 DESIGNATOR OF THE RUNWAY AFFECTED BY WIND SHEAR (INCLUDING ALL) CCITTIA5 0 0 32 CHARACTER 0 4 011071 TURBULENT VERTICAL MOMENTUM FLUX M**2/S**2 3 -128 14 M**2/S**2 3 5 011072 TURBULENT VERTICAL BUOYANCY FLUX KM/S 3 -128 11 KM/S 3 4 011073 TURBULENT KINETIC ENERGY M**2/S**2 2 -1024 13 M**2/S**2 2 4 011074 DISSIPATION ENERGY M**2/S**2 2 -1024 10 M**2/S**2 2 4 011075 MEAN TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 M**(2/3)/S 2 3 011076 PEAK TURBULENCE INTENSITY (EDDY DISSIPATION RATE) M**(2/3)/S 2 0 8 M**(2/3)/S 2 3 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 2 0 14 M/S 2 4 011230 MAXIMUM MEAN WIND SPEED M/S 1 -4096 13 M/S 1 4 011231 MEAN WIND SPEED M/S 1 -4096 13 M/S 1 4 011232 MINIMUM MEAN WIND SPEED M/S 1 -4096 13 M/S 1 4 011233 HIGHEST GUST DURING THE 10 MINUTE PERIOD PRECEDING OBSERVATION M/S 1 -4096 13 M/S 1 4 011233 HIGHEST GUST DURING THE 10 MINUTE PERIOD PRECEDING OBSERVATION M/S 1 -4096 13 M/S 1 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 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 012071 COLDEST CLUSTER TEMPERATURE K 1 0 12 K 1 4 012072 RADIANCE WM**(-2)SR**(-1) 6 0 31 WM**(-2)SR**(-1) 6 9 012073 TEMPERATURE K 2 0 16 C 2 4 012075 SPECTRAL RADIANCE WM**(-3)SR**(-1) -3 0 16 WM**(-3)SR**(-1) -3 5 012076 RADIANCE WM**(-2)SR**(-1) 3 0 16 WM**(-2)SR**(-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 012164 INSTRUMENT TEMPERATURE K 2 0 16 K 2 5 012171 COLDEST CLUSTER TEMPERATURE K 2 0 16 K 2 5 012193 COLDEST CLUSTER TEMPERATURE K 1 0 12 K 1 4 012194 RADIANCE W/M**2*STER*M**(-1) 6 0 31 W/M**2*STER*M**(-1) 6 10 012195 SPECTRAL RADIANCE W/M**2*STER*M**(-1) 10 0 31 W/M**2*STER*M**(-1) 10 10 012196 RADIANCE W/M**2*STER 3 0 16 W/M**2*STER 3 4 013001 SPECIFIC HUMIDITY KG/KG 5 0 14 KG/KG 5 5 013002 MIXING RATIO KG/KG 5 0 14 KG/KG 5 5 013003 RELATIVE HUMIDITY % 0 0 7 % 0 3 013004 VAPOUR PRESSURE PA -1 0 10 PA -1 4 013005 VAPOUR DENSITY KG/M**3 3 0 7 KG/M**3 3 3 013006 MIXING HEIGHTS M -1 -40 16 M -1 5 013007 MINIMUM RELATIVE HUMIDITY % 0 0 7 % 0 3 013008 MAXIMUM RELATIVE HUMIDITY % 0 0 7 % 0 3 013009 RELATIVE HUMIDITY % 1 -1000 12 % 1 4 013011 TOTAL PRECIPITATION/TOTAL WATER EQUIVALENT KG/M**2 1 -1 14 KG/M**2 1 5 013012 DEPTH OF FRESH SNOW M 2 -2 12 M 2 4 013013 TOTAL SNOW DEPTH M 2 -2 16 M 2 5 013014 RAINFALL/WATER EQUIVALENT OF SNOW (AVERAGED RATE) KG/(M**2)S 4 0 12 KG/(M**2)S 4 4 013015 SNOWFALL (AVERAGED RATE) M/S 7 0 12 M/S 7 4 013016 PRECIPITABLE WATER KG/M**2 0 0 7 KG/M**2 0 3 013019 TOTAL PRECIPITATION PAST 1 HOUR KG/M**2 1 -1 14 KG/M**2 1 4 013020 TOTAL PRECIPITATION PAST 3 HOURS KG/M**2 1 -1 14 KG/M**2 1 5 013021 TOTAL PRECIPITATION PAST 6 HOURS KG/M**2 1 -1 14 KG/M**2 1 5 013022 TOTAL PRECIPITATION PAST 12 HOURS KG/M**2 1 -1 14 KG/M**2 1 5 013023 TOTAL PRECIPITATION PAST 24 HOURS KG/M**2 1 -1 14 KG/M**2 1 5 013031 EVAPOTRANSPIRATION KG/M**2 0 0 7 KG/M**2 0 3 013032 EVAPORATION/EVAPOTRANSPIRATION KG/M**2 1 0 8 KG/M**2 1 3 013033 EVAPORATION/EVAPOTRANSPIRATION KG/M**2 1 0 10 KG/M**2 1 4 013038 SUPERADIABATIC INDICATOR CODE TABLE 13038 0 0 2 CODE TABLE 13038 0 1 013039 TERRAIN TYPE (ICE/SNOW) CODE TABLE 13039 0 0 3 CODE TABLE 13039 0 1 013040 SURFACE FLAG CODE TABLE 13040 0 0 4 CODE TABLE 13040 0 2 013041 PASQUILL-GIFFORD STABILITY CATEGORY CODE TABLE 13041 0 0 4 CODE TABLE 13041 0 2 013042 PARCEL LIFTED INDEX (TO 500 HPA) K 0 -20 6 K 0 2 013043 BEST LIFTED INDEX (TO 500 HPA) K 0 -20 6 K 0 2 013051 FREQUENCY GROUP, PRECIPITATION CODE TABLE 13051 0 0 4 CODE TABLE 13051 0 2 013052 HIGHEST DAILY AMOUNT OF PRECIPITATION KG/M**2 1 -1 14 KG/M**2 1 5 013055 INTENSITY OF PRECIPITATION KG/(M**2)S 4 0 8 MM H-1 1 4 013058 SIZE OF PRECIPITATING ELEMENT M 4 0 7 MM 1 3 013059 NUMBER OF FLASHES (THUNDERSTORM) NUMERIC 0 0 7 NUMERIC 0 3 013060 TOTAL ACCUMULATED PRECIPITATION KG/M**2 1 -1 17 KG/M**2 1 5 013071 UPSTREAM WATER LEVEL M 2 0 14 M 2 4 013072 DOWNSTREAM WATER LEVEL M 2 0 14 M 2 4 013073 MAXIMUM WATER LEVEL M 2 0 14 M 2 4 013080 WATER PH pH 1 0 10 pH 1 3 013081 WATER CONDUCTIVITY SIEMENS/M 3 0 14 SIEMENS/M 3 4 013082 WATER TEMPERATURE K 1 0 12 K 1 4 013083 DISSOLVED OXYGEN KG/M**3 6 0 15 KG/M**3 6 5 013084 TURBIDITY LUMEN 0 0 14 LUMEN 0 4 013085 OXYDATION REDUCTION POTENTIAL (ORP) V 3 0 14 V 3 4 013090 RADIOMETER WATER VAPOUR CONTENT KGM-2 1 0 10 KGM-2 1 4 013091 RADIOMETER LIQUID CONTENT KGM-2 2 0 8 KGM-2 2 3 014001 LONG-WAVE RADIATION, INTEGRATED OVER 24 HOURS J/M**2 -3 -2048 12 J/M**2 -3 4 014002 LONG-WAVE RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -3 -2048 12 J/M**2 -3 4 014003 SHORT-WAVE RADIATION, INTEGRATED OVER 24 HOURS J/M**2 -3 -2048 12 J/M**2 -3 4 014004 SHORT-WAVE RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -3 -2048 12 J/M**2 -3 4 014011 NET LONG-WAVE RADIATION, INTEGRATED OVER 24 HOURS J/M**2 -3 -2048 12 J/M**2 -3 4 014012 NET LONG-WAVE RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -3 -2048 12 J/M**2 -3 4 014013 NET SHORT-WAVE RADIATION, INTEGRATED OVER 24 HOURS J/M**2 -3 -2048 12 J/M**2 -3 4 014014 NET SHORT-WAVE RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -3 -2048 12 J/M**2 -3 4 014015 NET RADIATION, INTEGRATED OVER 24 HOURS J/M**2 -4 -16384 15 J/M**2 -4 5 014016 NET RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 -16384 15 J/M**2 -4 5 014017 INSTANTANEOUS LONG-WAVE RADIATION W/M**2 -3 -2048 12 W/M**2 -3 4 014018 INSTANTANEOUS SHORT-WAVE RADIATION W/M**2 -3 -2048 12 W/M**2 -3 4 014019 SURFACE ALBEDO % 0 0 7 % 0 3 014020 GLOBAL SOLAR RADIATION, INTEGRATED OVER 24 HOURS J/M**2 -4 0 15 J/M**2 -4 5 014021 GLOBAL SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 J/M**2 -4 5 014022 DIFFUSE SOLAR RADIATION, INTEGRATED OVER 24 HOURS J/M**2 -4 0 15 J/M**2 -4 5 014023 DIFFUSE SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 J/M**2 -4 5 014024 DIRECT SOLAR RADIATION, INTEGRATED OVER 24 HOURS J/M**2 -4 0 15 J/M**2 -4 5 014025 DIRECT SOLAR RADIATION, INTEGRATED OVER PERIOD SPECIFIED J/M**2 -4 0 15 J/M**2 -4 5 014026 ALBEDO AT THE TOP OF CLOUDS % 0 0 7 % 0 3 014027 ALBEDO % 0 0 7 % 0 3 014028 GLOBAL SOLAR RADIATION (HIGH ACCURACY), INTEGRATED OVER PERIOD S J/M**2 -2 0 16 J/M**2 -2 5 014029 DIFFUSE SOLAR RADIATION (HIGH ACCURACY), INTEGRATED OVER PERIOD J/M**2 -2 0 16 J/M**2 -2 5 014030 DIRECT SOLAR RADIATION (HIGH ACCURACY), INTEGRATED OVER PERIOD S J/M**2 -2 0 16 J/M**2 -2 5 014031 TOTAL SUNSHINE MINUTE 0 0 11 MINUTE 0 4 014032 TOTAL SUNSHINE HOUR 0 0 10 HOUR 0 4 014033 TOTAL SUNSHINE % 0 0 9 % 0 3 014034 SUNSHINE OVER PERIOD SPECIFIED MINUTE 0 0 11 MINUTE 0 4 014042 BI-DIRECTIONAL REFLECTANCE % 0 0 7 % 0 3 014045 CHANNEL RADIANCE (W/M**2)*(1/SR)*CM 0 0 11 WM-2SR-1CM-1 0 4 014050 EMISSIVITY (SEE NOTE 5) % 1 0 10 % 1 4 014051 DIRECT SOLAR RADIATION INTEGRATED OVER LAST HOUR J/M**2 -3 0 14 JM-2 -3 4 015001 TOTAL OZONE DU 0 0 10 DU 0 4 015002 AIR MASS (SLANT PATH AT 22 KM) NUMERIC 2 0 10 NUMERIC 2 3 015003 MEASURED OZONE PARTIAL PRESSURE (SOUNDING) PA 4 0 9 NBAR 0 3 015004 OZONE SOUNDING CORRECTION FACTOR NUMERIC 3 0 11 NUMERIC 3 4 015005 OZONE P DU 0 0 10 DU 0 3 015011 LOG 10 OF INTEGRATED ELECTRON DENSITY LOG (1/M2) 3 14000 13 LOG (M-2) 3 4 015015 MAXIMUM IMAGE SPECTRAL COMPONENT BEFORE NORMALIZATION NUMERIC 0 0 31 NUMERIC 0 10 015020 INTEGRATED 03 DENSITY KG/M**2 8 0 21 KG/M**2 8 7 015031 ATMOSPHERIC PATH DELAY IN SATELLITE SIGNAL M 4 10000 15 M 4 5 015032 ESTIMATED ERROR IN ATMOSPHERIC PATH DELAY M 4 0 10 M 4 4 015033 DIFFERENCE IN PATH DELAYS FOR LIMB VIEWS AT EXTREMES OF SCAN M 5 -10000 15 M 5 5 015034 ESTIMATED ERROR IN PATH DELAY DIFFERENCE M 5 0 14 M 5 5 015035 COMPONENT OF ZENITH PATH DELAY DUE TO WATER VAPOUR M 4 0 14 M 4 5 019001 TYPE OF SYNOPTIC FEATURE CODE TABLE 19001 0 0 6 CODE TABLE 19001 0 2 019002 EFFECTIVE RADIUS OF FEATURE M -2 0 12 M -2 4 019003 WIND SPEED THRESHOLD M/S 0 0 8 M/S 0 3 019004 EFFECTIVE RADIUS WITH RESPECT TO WIND SPEEDS ABOVE THRESHOLD M -2 0 12 M -2 4 019005 DIRECTION OF MOTION OF FEATURE DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 019006 SPEED OF MOTION OF FEATURE M/S 2 0 14 M/S 2 5 019007 EFFECTIVE RADIUS OF FEATURE M -3 0 12 M -3 4 019008 VERTICAL EXTENT OF CIRCULATION CODE TABLE 19008 0 0 3 CODE TABLE 19008 0 1 019009 EFFECTIVE RADIUS WITH RESPECT TO WIND SPEEDS ABOVE THRESHOLD (LA M -3 0 12 M -3 4 019010 METHOD FOR TRACKING THE CENTRE OF SYNOPTIC FEATURE CODE TABLE 19010 0 0 4 CODE TABLE 19010 0 2 020001 HORIZONTAL VISIBILITY M -1 0 13 M -1 4 020002 VERTICAL VISIBILITY M -1 0 7 M -1 3 020003 PRESENT WEATHER (SEE NOTE 1) CODE TABLE 20003 0 0 9 CODE TABLE 20003 0 3 020004 PAST WEATHER (1) (SEE NOTE 2) CODE TABLE 20004 0 0 5 CODE TABLE 20004 0 2 020005 PAST WEATHER (2) (SEE NOTE 2) CODE TABLE 20005 0 0 5 CODE TABLE 20005 0 2 020008 CLOUD DISTRIBUTION FOR AVIATION CODE TABLE 20008 0 0 5 CODE TABLE 20008 0 2 020009 GENERAL WEATHER INDICATOR (TAF/METAR) CODE TABLE 20009 0 0 4 CODE TABLE 20009 0 2 020010 CLOUD COVER (TOTAL) % 0 0 7 % 0 3 020011 CLOUD AMOUNT CODE TABLE 20011 0 0 4 CODE TABLE 20011 0 2 020012 CLOUD TYPE CODE TABLE 20012 0 0 6 CODE TABLE 20012 0 2 020013 HEIGHT OF BASE OF CLOUD M -1 -40 11 M -1 4 020014 HEIGHT OF TOP OF CLOUD M -1 -40 11 M -1 4 020015 PRESSURE AT BASE OF CLOUD PA -1 0 14 PA -1 5 020016 PRESSURE AT TOP OF CLOUD PA -1 0 14 PA -1 5 020017 CLOUD TOP DESCRIPTION CODE TABLE 20017 0 0 4 CODE TABLE 20017 0 2 020018 TENDENCY OF RUNWAY VISUAL RANGE CODE TABLE 20018 0 0 2 CODE TABLE 20018 0 1 020019 SIGNIFICANT PRESENT OR FORECAST WEATHER CCITTIA5 0 0 72 CHARACTER 0 9 020020 SIGNIFICANT RECENT WEATHER PHENOMENA CCITTIA5 0 0 32 CHARACTER 0 4 020021 TYPE OF PRECIPITATION FLAG TABLE 20021 0 0 30 FLAG TABLE 20021 0 10 020022 CHARACTER OF PRECIPITATION CODE TABLE 20022 0 0 4 CODE TABLE 20022 0 2 020023 OTHER WEATHER PHENOMENA FLAG TABLE 20023 0 0 18 FLAG TABLE 20023 0 6 020024 INTENSITY OF PHENOMENA CODE TABLE 20024 0 0 3 CODE TABLE 20024 0 1 020025 OBSCURATION FLAG TABLE 20025 0 0 21 FLAG TABLE 20025 0 7 020026 CHARACTER OF OBSCURATION CODE TABLE 20026 0 0 4 CODE TABLE 20026 0 2 020027 PHENOMENA OCCURRENCE FLAG TABLE 20027 0 0 9 FLAG TABLE 20027 0 3 020029 RAIN FLAG CODE TABLE 20029 0 0 2 CODE TABLE 20029 0 1 020031 ICE DEPOSIT (THICKNESS) M 2 0 7 M 2 3 020032 RATE OF ICE ACCRETION CODE TABLE 20032 0 0 3 CODE TABLE 20032 0 1 020033 CAUSE OF ICE ACCRETION FLAG TABLE 20033 0 0 4 FLAG TABLE 20033 0 2 020034 SEA ICE CONCENTRATION CODE TABLE 20034 0 0 5 CODE TABLE 20034 0 2 020035 AMOUNT AND TYPE OF ICE CODE TABLE 20035 0 0 4 CODE TABLE 20035 0 2 020036 ICE SITUATION CODE TABLE 20036 0 0 5 CODE TABLE 20036 0 2 020037 ICE DEVELOPMENT CODE TABLE 20037 0 0 5 CODE TABLE 20037 0 2 020038 BEARING OF ICE EDGE (SEE NOTE 3) DEGREE TRUE 0 0 12* DEGREE TRUE 0 3 020039 ICE DISTANCE M -1 0 13 M -1 4 020041 AIRFRAME ICING CODE TABLE 20041 0 0 4 CODE TABLE 20041 0 2 020042 AIRFRAME ICING PRESENT CODE TABLE 20042 0 0 2 CODE TABLE 20042 0 1 020043 PEAK LIQUID WATER CONTENT KG/M**3 4 0 7 KG/M**3 4 2 020044 AVERAGE LIQUID WATER CONTENT KG/M**3 4 0 7 KG/M**3 4 2 020045 SUPERCOOLED LARGE DROPLET (SLD) CONDITIONS CODE TABLE 20045 0 0 2 CODE TABLE 20045 0 1 020051 AMOUNT OF LOW CLOUDS % 0 0 7 % 0 3 020052 AMOUNT OF MIDDLE CLOUDS % 0 0 7 % 0 3 020053 AMOUNT OF HIGH CLOUDS % 0 0 7 % 0 3 020061 RUNWAY VISUAL RANGE (RVR) M 0 0 12 M 0 4 020062 STATE OF THE GROUND (WITH OR WITHOUT SNOW) CODE TABLE 20062 0 0 5 CODE TABLE 20062 0 2 020063 SPECIAL PHENOMENA CODE TABLE 20063 0 0 10 CODE TABLE 20063 0 4 020065 SNOW COVER (SEE NOTE 4) % 0 0 7 % 0 3 020070 MINIMUM NUMBER OF ATMOSPHERICS NUMERIC 0 0 7 NUMERIC 0 3 020071 ACCURACY OF FIX AND RATE OF ATMOSPHERICS CODE TABLE 20071 0 0 4 CODE TABLE 20071 0 2 020081 CLOUD AMOUNT IN SEGMENT % 0 0 7 % 0 3 020082 AMOUNT SEGMENT CLOUD FREE % 0 0 7 % 0 3 020090 SPECIAL CLOUDS CODE TABLE 20090 0 0 4 CODE TABLE 20090 0 2 020192 SPECIAL PHENOMENA CODE TABLE 20192 0 0 14 CODE TABLE 0 5 021001 HORIZONTAL REFLECTIVITY dB 0 -64 7 dB 0 3 021002 VERTICAL REFLECTIVITY dB 0 -64 7 dB 0 3 021003 DIFFERENTIAL REFLECTIVITY dB 1 -5 7 dB 1 3 021005 LINEAR DEPOLARISATION RATIO dB 0 -65 6 dB 0 2 021006 CIRCULAR DEPOLARISATION RATIO dB 0 -65 6 dB 0 2 021011 DOPPLER MEAN VELOCITY IN X-DIRECTION M/S 0 -128 8 M/S 0 3 021012 DOPPLER MEAN VELOCITY IN Y-DIRECTION M/S 0 -128 8 M/S 0 3 021013 DOPPLER MEAN VELOCITY IN Z-DIRECTION M/S 0 -128 8 M/S 0 3 021014 DOPPLER MEAN VELOCITY (RADIAL) M/S 1 -4096 13 M/S 1 4 021017 DOPPLER VELOCITY SPECTRAL WIDTH M/S 1 0 8 M/S 1 3 021021 ECHO TOPS M -3 0 4 M -3 2 021030 SIGNAL TO NOISE RATIO dB 0 -32 8 dB 0 3 021031 VERTICALLY INTEGRATED LIQUID-WATER CONTENT KG/M**2 0 0 7 KG/M**2 0 3 021036 RADAR RAINFALL INTENSITY M/S 7 0 12 M/S 7 4 021041 BRIGHT-BAND HEIGHT M -2 0 8 M -2 3 021051 SIGNAL POWER ABOVE 1 MW dB 0 -256 8 dB 0 3 021062 BACKSCATTER dB 2 -5000 13 dB 2 4 021063 RADIOMETRIC RESOLUTION (NOISE VALUE) % 1 0 10 % 1 4 021064 CLUTTER NOISE ESTIMATE NUMERIC 0 0 8 NUMERIC 0 3 021065 MISSING PACKET COUNTER NUMERIC 0 -127 8 NUMERIC 0 3 021066 WAVE SCATTEROMETER PRODUCT CONFIDENCE DATA FLAG TABLE 21066 0 0 12 FLAG TABLE 21066 0 4 021067 WIND PRODUCT CONFIDENCE DATA FLAG TABLE 21067 0 0 13 FLAG TABLE 21067 0 5 021068 RADAR ALTIMETER PRODUCT CONFIDENCE DATA FLAG TABLE 21068 0 0 8 FLAG TABLE 21068 0 3 021069 SST PRODUCT CONFIDENCE DATA FLAG TABLE 21069 0 0 10 FLAG TABLE 21069 0 4 021070 SST PRODUCT CONFIDENCE DATA (SADIST-2) FLAG TABLE 21070 0 0 23 FLAG TABLE 21070 0 6 021071 PEAKINESS NUMERIC 0 0 16 NUMERIC 0 5 021072 SATELLITE ALTIMETER CALIBRATION STATUS FLAG TABLE 21072 0 0 4 FLAG TABLE 21072 0 2 021073 SATELLLITE ALTIMETER INSTRUMENT MODE FLAG TABLE 21073 0 0 9 FLAG TABLE 21073 0 3 021075 IMAGE SPECTRUM INTENSITY NUMERIC 0 0 8 NUMERIC 0 3 021076 REPRESENTATION OF INTENSITIES CODE TABLE 21076 0 0 3 CODE TABLE 21076 0 1 021077 ALTITUDE CORRECTION (IONOSPHERE) M 3 0 14 M 3 5 021078 ALTITUDE CORRECTION (DRY TROPOSPHERE) M 3 0 9 M 3 3 021079 ALTITUDE CORRECTION (WET TROPOSPHERE) M 3 2000 10 M 3 4 021080 ALTITUDE CORRECTION (CALIBRATION CONSTANT) M 3 0 11 M 3 4 021081 OPEN LOOP CORRECTION (HEIGHT-TIME LOOP) M 3 0 10 M 3 4 021082 OPEN LOOP CORRECTION (AUTO GAIN CONTROL) dB 3 -3000 14 dB 3 5 021083 WARM TARGET CALIBRATION NUMERIC 0 0 16 NUMERIC 0 5 021084 COLD TARGET CALIBRATION NUMERIC 0 0 16 NUMERIC 0 5 021085 ATSR SEA SURFACE TEMPERATURE ACROSS- TRACK BAND NUMBER NUMERIC 0 0 4 NUMERIC 0 2 021091 RADAR SIGNAL DOPPLER SPECTRUM 0TH MOMENT dB 0 -100 8 dB 0 3 021092 RASS SIGNAL DOPPLER SPECTRUM 0TH MOMENT, REFERRING TO RASS SIGNA dB 0 -100 8 dB 0 3 021101 NUMBER OF VECTOR AMBIGUITIES NUMERIC 0 0 3 NUMERIC 0 1 021102 INDEX OF SELECTED WIND VECTOR NUMERIC 0 0 3 NUMERIC 0 1 021103 TOTAL NUMBER OF SIGMA-0 MEASUREMENTS NUMERIC 0 0 5 NUMERIC 0 2 021104 LIKELIHOOD COMPUTED FOR SOLUTION NUMERIC 3 -30000 15 NUMERIC 3 5 021105 NORMALIZED RADAR CROSS-SECTION dB 2 -10000 14 dB 2 5 021106 KP VARIANCE COEFFICIENT (ALPHA) NUMERIC 3 0 14 NUMERIC 3 5 021107 KP VARIANCE COEFFICIENT (BETA) NUMERIC 8 0 16 NUMERIC 8 5 021109 SEAWINDS WIND VECTOR CELL QUALITY FLAG TABLE 21109 0 0 17 FLAG TABLE 21109 0 6 021110 NUMBER OF INNER-BEAM SIGMA-0 (FORWARD OF SATELLITE) NUMERIC 0 0 6 NUMERIC 0 2 021111 NUMBER OF OUTER-BEAM SIGMA-0 (FORWARD OF SATELLITE) NUMERIC 0 0 6 NUMERIC 0 2 021112 NUMBER OF INNER-BEAM SIGMA-0 (AFT OF SATELLITE) NUMERIC 0 0 6 NUMERIC 0 2 021113 NUMBER OF OUTER-BEAM SIGMA-0 (AFT OF SATELLITE) NUMERIC 0 0 6 NUMERIC 0 2 021114 KP VARIANCE COEFFICENT (GAMMA) dB 3 -140000 18 dB 3 6 021115 SEAWINDS SIGMA-0 QUALITY FLAG TABLE 21115 0 0 17 FLAG TABLE 21115 0 6 021116 SEAWINDS SIGMA-0 MODE FLAG TABLE 21116 0 0 17 FLAG TABLE 21116 0 6 021117 SIGMA-0 VARIANCE QUALITY CONTROL NUMERIC 2 0 16 NUMERIC 2 5 021118 ATTENUATION CORRECTION ON SIGMA-0 dB 2 -10000 14 dB 2 5 021119 WIND SCATTEROMETER GEOPHYSICAL MODEL FUNCTION CODE TABLE 21119 0 0 6 CODE TABLE 21119 0 2 021120 PROBABILITY OF RAIN NUMERIC 3 0 10 NUMERIC 3 4 021121 SEAWINDS NOF* RAIN INDEX NUMERIC 0 0 8 NUMERIC 0 3 021122 ATTENUATION CORRECTION OF SIGMA-0 (FROM TB) dB 2 -10000 14 dB 2 5 021123 SEAWINDS NORMALIZED RADAR CROSS SECTION dB 2 -30000 15 dB 2 5 021128 NUMBER OF VALID POINTS PER SECOND USED TO DERIVE PREVIOUS PARAME NUMERIC 0 0 8 NUMERIC 0 3 021192 RADAR BACK SCATTER dB 2 -5000 13 dB 2 4 021193 NOISE FIGURE % 0 0 7 % 0 3 021194 BACKGROUND NOISE LEVEL NUMERIC 0 0 8 NUMERIC 0 3 021195 MISSING PACKET COUNTER NUMERIC 0 -127 8 NUMERIC 0 3 022001 DIRECTION OF WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022002 DIRECTION OF WIND WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022003 DIRECTION OF SWELL WAVES DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022004 DIRECTION OF CURRENT DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022011 PERIOD OF WAVES S 0 0 6 S 0 2 022012 PERIOD OF WIND WAVES S 0 0 6 S 0 2 022013 PERIOD OF SWELL WAVES S 0 0 6 S 0 2 022021 HEIGHT OF WAVES M 1 0 10 M 1 4 022022 HEIGHT OF WIND WAVES M 1 0 10 M 1 4 022023 HEIGHT OF SWELL WAVES M 1 0 10 M 1 4 022025 STANDARD DEVIATION WAVE HEIGHT M 2 0 10 M 2 4 022026 STANDARD DEVIATION OF SIGNIFICANT WAVE HEIGHT M 2 0 10 M 2 4 022031 SPEED OF CURRENT M/S 2 0 13 M/S 2 4 022035 TIDAL ELEVATION WITH RESPECT TO LOCAL CHART DATUM M 2 0 14 M 2 4 022036 METEOROLOGICAL RESIDUAL TIDAL ELEVATION (SURGE OR OFFSET) M 2 0 14 M 2 4 022037 TIDAL ELEVATION WITH RESPECT TO NATIONAL LAND DATUM M 3 -10000 15 M 3 5 022038 TIDAL ELEVATION WITH RESPECT TO LOCAL CHART DATUM M 3 -10000 15 M 3 5 022039 METEOROLOGICAL RESIDUAL TIDAL ELEVATION (SURGE OR OFFSET) M 3 -5000 12 M 3 4 022040 METEOROLOGICAL RESIDUAL TIDAL ELEVATION (SURGE OR OFFSET) M 3 -5000 14 M 3 5 022041 SEA-SURFACE TEMPERATURE (15-DAY RUNNING MEAN) K 1 0 12 K 1 4 022042 SEA/WATER TEMPERATURE K 1 0 12 K 1 4 022043 SEA/WATER TEMPERATURE K 2 0 15 K 2 5 022044 SOUND VELOCITY M/S 1 0 14 M/S 1 5 022045 SEA/WATER TEMPERATURE K 3 0 19 K 3 6 022050 STANDARD DEVIATION SEA-SURFACE TEMPERATURE K 2 0 8 K 2 3 022055 FLOAT CYCLE NUMBER NUMERIC 0 0 10 NUMERIC 0 3 022056 DIRECTION OF PROFILE CODE TABLE 22056 0 0 2 CODE TABLE 22056 0 1 022060 LAGRANGIAN DRIFTER DROGUE STATUS CODE TABLE 022060 0 0 3 CODE TABLE 22060 0 1 022061 STATE OF THE SEA CODE TABLE 22061 0 0 4 CODE TABLE 22061 0 2 022062 SALINITY PART PER THOUSAND 2 0 14 PART PER THOUSAND 2 5 022063 TOTAL WATER DEPTH M 0 0 14 M 0 5 022064 SALINITY PART PER THOUSAND 3 0 17 PART PER THOUSAND 3 6 022065 WATER PRESSURE PA -3 0 17 PA -3 6 022066 WATER CONDUCTIVITY S M-1 6 0 26 S M-1 6 8 022067 INSTRUMENT TYPE FOR WATER TEMPERATURE PROFILE MEASUREMENT CODE TABLE 22067 0 0 10 CODE TABLE 22067 0 4 022068 WATER TEMPERATURE PROFILE RECORDER TYPES CODE TABLE 22068 0 0 7 CODE TABLE 22068 0 3 022070 SIGNIFICANT WAVE HEIGHT M 2 0 13 M 2 4 022071 SPECTRAL PEAK WAVE PERIOD S 1 0 9 S 1 3 022072 SPECTRAL PEAK WAVE LENGTH M 0 0 13 M 0 4 022073 MAXIMUM WAVE HEIGHT M 2 0 13 M 2 4 022074 AVERAGE WAVE PERIOD S 1 0 9 S 1 3 022075 AVERAGE WAVE LENGTH M 0 0 13 M 0 4 022076 DIRECTION FROM WHICH DOMINANT WAVES ARE COMING DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022077 DIRECTIONAL SPREAD OF DOMINANT WAVE DEGREE 0 0 9 DEGREE 0 3 022078 DURATION OF WAVE RECORD S 0 0 12 S 0 4 022079 LENGTH OF WAVE RECORD M 0 0 16 M 0 5 022080 WAVEBAND CENTRAL FREQUENCY Hz 3 0 10 Hz 3 4 022081 WAVEBAND CENTRAL WAVE NUMBER 1/M 5 0 13 1/M 5 4 022082 MAXIMUM NON-DIRECTIONAL SPECTRAL WAVE DENSITY M**2S 2 0 20 M**2S 2 7 022083 MAXIMUM NON-DIRECTIONAL SPECTRAL WAVE NUMBER M**3 2 0 20 M**3 2 7 022084 BAND CONTAINING MAXIMUM NON- DIRECTIONAL SPECTRAL WAVE DENSITY NUMERIC 0 0 7 NUMERIC 0 3 022085 SPECTRAL WAVE DENSITY RATIO NUMERIC 0 0 7 NUMERIC 0 3 022086 MEAN DIRECTION FROM WHICH WAVES ARE COMING DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022087 PRINCIPAL DIRECTION FROM WHICH WAVES ARE COMING DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022088 FIRST NORMALIZED POLAR COORDINATE FROM FOURIER COEFFICIENTS NUMERIC 2 0 7 NUMERIC 2 3 022089 SECOND NORMALIZED POLAR COORDINATE FROM FOURIER COEFFICIENTS NUMERIC 2 0 7 NUMERIC 2 3 022090 NON-DIRECTIONAL SPECTRAL ESTIMATE BY WAVE FREQUENCY M**2S 2 0 20 M**2S 2 7 022091 NON-DIRECTIONAL SPECTRAL ESTIMATE BY WAVE NUMBER M**3 2 0 20 M**3 2 7 022092 DIRECTIONAL SPECTRAL ESTIMATE BY WAVE FREQUENCY M**2S/RAD 2 0 20 M**2S/RAD 2 7 022093 DIRECTIONAL SPECTRAL ESTIMATE BY WAVE NUMBER M**4 2 0 20 M**4 2 7 022094 TOTAL NUMBER OF WAVE BANDS NUMERIC 0 0 7 NUMERIC 0 3 022095 DIRECTIONAL SPREAD OF INDIVIDUAL WAVES DEGREE 0 0 8 DEGREE 0 3 022096 SPECTRAL BAND WIDTH 1/S 3 0 4 1/S 3 2 022097 MEAN WAVELENGTH > 731 M OF IMAGE SPECTRUM AT LOW WAVE NUMBERS M 0 0 14 M 0 5 022098 WAVELENGTH SPREAD (WAVELENGTH > 731 M) AT LOW WAVE NUMBERS M 0 0 14 M 0 5 022099 MEAN DIRECTION AT LOW WAVE NUMBERS (WAVELENGTH > 731 M) DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 022100 DIRECTION SPREAD AT LOW WAVE NUMBERS(WAVELENGTH > 731 M) DEGREE 0 0 9 DEGREE 0 3 022101 TOTAL ENERGY (WAVELENGTH > 731M) AT LOW WAVE NUMBERS NUMERIC 0 0 31 NUMERIC 0 10 022120 TIDE STATION AUTOMATED WATER LEVEL CHECK CODE TABLE 22120 0 0 5 CODE TABLE 22120 0 2 022121 TIDE STATION MANUAL WATER LEVEL CHECK CODE TABLE 22121 0 0 5 CODE TABLE 22121 0 2 022122 TIDE STATION AUTOMATED METEOROLOGICAL DATA CHECK CODE TABLE 22122 0 0 5 CODE TABLE 22122 0 2 022123 TIDE STATION MANUAL METEOROLOGICAL DATA CHECK CODE TABLE 22123 0 0 5 CODE TABLE 22123 0 2 022141 SEA-SURFACE TEMPERATURE (15-DAY RUNNING MEAN) K 2 0 15 K 2 5 023001 ACCIDENT EARLY NOTIFICATION - ARTICLE APPLICABLE CODE TABLE 23001 0 0 3 CODE TABLE 23001 0 1 023002 ACTIVITY OR FACILITY INVOLVED IN INCIDENT CODE TABLE 23002 0 0 5 CODE TABLE 23002 0 2 023003 TYPE OF RELEASE CODE TABLE 23003 0 0 3 CODE TABLE 23003 0 1 023004 COUNTERMEASURES TAKEN NEAR BORDER CODE TABLE 23004 0 0 3 CODE TABLE 23004 0 1 023005 CAUSE OF INCIDENT CODE TABLE 23005 0 0 2 CODE TABLE 23005 0 1 023006 INCIDENT SITUATION CODE TABLE 23006 0 0 3 CODE TABLE 23006 0 1 023007 CHARACTERISTICS OF RELEASE CODE TABLE 23007 0 0 3 CODE TABLE 23007 0 1 023008 STATE OF CURRENT RELEASE CODE TABLE 23008 0 0 2 CODE TABLE 23008 0 1 023009 STATE OF EXPECTED RELEASE CODE TABLE 23009 0 0 2 CODE TABLE 23009 0 1 023016 POSSIBILITY OF SIGNIFICANT CHEMICAL TOXIC HEALTH EFFECT CODE TABLE 23016 0 0 2 CODE TABLE 23016 0 1 023017 FLOW DISCHARGE OF MAJOR RECIPIENT M**3/S 6 0 20 M**3/S 6 7 023018 RELEASE BEHAVIOUR OVER TIME CODE TABLE 23018 0 0 3 CODE TABLE 23018 0 1 023019 ACTUAL RELEASE HEIGHT M 0 -15000 17 M 0 6 023021 EFFECTIVE RELEASE HEIGHT M 0 -15000 17 M 0 6 023022 DISTANCE OF RELEASE POINT OR SITE OF INCIDENT M 0 0 24 M 0 8 023023 MAIN TRANSPORT SPEED IN THE ATMOSPHERE M/S 1 0 12 M/S 1 4 023024 MAIN TRANSPORT SPEED IN WATER M/S 2 0 13 M/S 2 4 023025 MAIN TRANSPORT SPEED IN GROUND WATER M/S 2 0 13 M/S 2 4 023027 MAIN TRANSPORT DIRECTION IN THE ATMOSPHERE DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 023028 MAIN TRANSPORT DIRECTION IN WATER DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 023029 MAIN TRANSPORT DIRECTION IN GROUND WATER DEGREE TRUE 0 0 9 DEGREE TRUE 0 3 023031 POSSIBILITY THAT PLUME WILL ENCOUNTER PRECIPITATION IN STATE IN CODE TABLE 23031 0 0 2 CODE TABLE 23031 0 1 023032 PLUME WILL ENCOUNTER CHANGE IN WIND DIRECTION AND/OR SPEED FLAG CODE TABLE 23032 0 0 2 CODE TABLE 23032 0 1 024001 ESTIMATE OF AMOUNT OF RADIOACTIVITY RELEASED UP TO SPECIFIED TIM Bq -11 0 28 Bq -11 9 024002 ESTIMATED MAXIMUM POTENTIAL RELEASE Bq -11 0 28 Bq -11 9 024003 COMPOSITION OF RELEASE CODE TABLE 24003 0 0 5 CODE TABLE 24003 0 2 024004 ELEMENT NAME CCITTIA5 0 0 16 CHARACTER 0 2 024005 ISOTOPE MASS NUMERIC 0 0 9 NUMERIC 0 3 024011 DOSE mSv 2 0 32 mSv 2 10 024012 TRAJECTORY DOSE (DEFINED LOCATION AND EXPECTED TIME OF ARRIVAL) mSv 2 0 32 mSv 2 10 024013 GAMMA DOSE IN AIR ALONG THE MAIN TRANSPORT PATH (DEFINED LOCATIO mSv 2 0 32 mSv 2 10 024021 AIR CONCENTRATION (OF NAMED ISOTOPE TYPE INCLUDING GROSS BETA) Bq/M**3 2 0 32 Bq/M**3 2 10 024022 CONCENTRATION IN PRECIPITATION (OF NAMES ISOTOPE TYPE) Bq/L 2 0 32 BQ L-1 2 10 024023 PULSE RATE OF BETA RADIATION 1/S 1 0 14 1/S 1 4 024024 PULSE RATE OF GAMMA RADIATION 1/S 1 0 14 1/S 1 4 025001 RANGE-GATE LENGTH M -1 0 6 M -1 2 025002 NUMBER OF GATES AVERAGED NUMERIC 0 0 4 NUMERIC 0 2 025003 NUMBER OF INTEGRATED PULSES NUMERIC 0 0 8 NUMERIC 0 3 025004 ECHO PROCESSING CODE TABLE 25004 0 0 2 CODE TABLE 25004 0 1 025005 ECHO INTEGRATION CODE TABLE 25005 0 0 2 CODE TABLE 25005 0 1 025006 Z TO R CONVERSION CODE TABLE 25006 0 0 3 CODE TABLE 25006 0 1 025007 Z TO R CONVERSION FACTOR NUMERIC 0 0 12 NUMERIC 0 4 025008 Z TO R CONVERSION EXPONENT NUMERIC 2 0 9 NUMERIC 2 3 025009 CALIBRATION METHOD FLAG TABLE 25009 0 0 4 FLAG TABLE 25009 0 2 025010 CLUTTER TREATMENT CODE TABLE 25010 0 0 4 CODE TABLE 25010 0 2 025011 GROUND OCCULTATION CORRECTION (SCREENING) CODE TABLE 25011 0 0 2 CODE TABLE 25011 0 1 025012 RANGE ATTENUATION CORRECTION CODE TABLE 25012 0 0 2 CODE TABLE 25012 0 1 025013 BRIGHT-BAND CORRECTION FLAG TABLE 25013 0 0 2 FLAG TABLE 25013 0 1 025014 AZIMUTH CLUTTER CUT-OFF (SEE NOTE 1) NUMERIC 0 0 12 NUMERIC 0 4 025015 RADOME ATTENUATION CORRECTION FLAG TABLE 25015 0 0 2 FLAG TABLE 25015 0 1 025016 CLEAR-AIR ATTENUATION CORRECTION dB/M 5 0 6 dB/M 5 2 025017 PRECIPITATION ATTENUATION CORRECTION FLAG TABLE 25017 0 0 2 FLAG TABLE 25017 0 1 025018 A TO Z LAW FOR ATTENUATION FACTOR NUMERIC 7 0 6 NUMERIC 7 2 025019 A TO Z LAW FOR ATTENUATION EXPONENT NUMERIC 2 0 7 NUMERIC 2 3 025020 MEAN SPEED ESTIMATION CODE TABLE 25020 0 0 2 CODE TABLE 25020 0 1 025021 WIND COMPUTATION ENHANCEMENT FLAG TABLE 25021 0 0 8 FLAG TABLE 25021 0 3 025025 BATTERY VOLTAGE V 1 0 9 V 1 3 025026 BATTERY VOLTAGE (LARGE RANGE) V 1 0 12 V 1 4 025028 OPERATOR OR MANUFACTURER DEFINED PARAMETER NUMERIC 1 -16384 15 NUMERIC 1 5 025030 RUNNING MEAN SEA-SURFACE TEMPERATURE USAGE CODE TABLE 25030 0 0 2 CODE TABLE 25030 0 1 025032 WIND PROFILER MODE INFORMATION CODE TABLE 25032 0 0 2 CODE TABLE 25032 0 1 025033 WIND PROFILER SUBMODE INFORMATION* CODE TABLE 25033 0 0 2 CODE TABLE 25033 0 1 025034 WIND PROFILER QUALITY CONTROL TEST RESULTS* FLAG TABLE 25034 0 0 4 FLAG TABLE 25034 0 2 025036 ATMOSPHERICS LOCATION METHOD CODE TABLE 25036 0 0 4 CODE TABLE 25036 0 2 025040 CO2 WIND PRODUCT DERIVATION CODE TABLE 25040 0 0 4 CODE TABLE 25040 0 2 025041 MOVING PLATFORM DIRECTION REPORTING METHOD CODE TABLE 25041 0 0 2 CODE TABLE 25041 0 1 025042 MOVING PLATFORM SPEED REPORTING METHOD CODE TABLE 25042 0 0 2 CODE TABLE 25042 0 1 025043 WAVE SAMPLING INTERVAL (TIME) S 4 0 15 S 4 5 025044 WAVE SAMPLING INTERVAL (SPACE) M 2 0 14 M 2 5 025045 HIRS CHANNEL COMBINATION FLAG TABLE 25045 0 0 21 FLAG TABLE 25045 0 7 025046 MSU CHANNEL COMBINATION FLAG TABLE 25046 0 0 5 FLAG TABLE 25046 0 2 025047 SSU CHANNEL COMBINATION FLAG TABLE 25047 0 0 4 FLAG TABLE 25047 0 2 025048 AMSU-A CHANNEL COMBINATION FLAG TABLE 25048 0 0 16 FLAG TABLE 25048 0 6 025049 AMSU-B CHANNEL COMBINATION FLAG TABLE 25049 0 0 6 FLAG TABLE 25049 0 2 025051 AVHRR CHANNEL COMBINATION FLAG TABLE 25051 0 0 7 FLAG TABLE 25051 0 3 025053 OBSERVATION QUALITY FLAG TABLE 25053 0 0 12 FLAG TABLE 25053 0 4 025054 SSMIS SUBFRAME ID NEMBER NUMERIC 0 0 5 NUMERIC 0 2 025055 MULTIPLEXER HOUSEKEEPING K 2 0 16 K 2 5 025060 SOFTWARE IDENTIFICATION (SEE NOTE 2) NUMERIC 0 0 14 NUMERIC 0 5 025061 SOFTWARE IDENTIFICATION AND VERSION NUMBER CCITTIA5 0 0 96 CHARACTER 0 12 025065 ORIENTATION CORRECTION (AZIMUTH) DEGREE 2 -1000 11 DEGREE 2 4 025066 ORIENTATION CORRECTION (ELEVATION) DEGREE 2 -1000 11 DEGREE 2 4 025067 RADIOSONDE RELEASE POINT PRESSURE CORRECTION PA 0 -8000 14 PA 0 4 025068 NUMBER OF ARCHIVE RECOMPUTES NUMERIC 0 0 7 NUMERIC 0 3 025069 FLIGHT LEVEL PRESSURE CORRECTIONS FLAG TABLE 25069 0 0 8 FLAG TABLE 25069 0 3 025070 MAJOR FRAME COUNT NUMERIC 0 0 4 NUMERIC 0 2 025071 FRAME COUNT NUMERIC 0 0 5 NUMERIC 0 2 025075 SATELLITE ANTENNA CORRECTIONS VERSION NUMBER NUMERIC 0 0 5 NUMERIC 0 2 025076 LOG-10 OF (TEMPERATURE-RADIANCE CENTRAL WAVE NUMBER) FOR ATOVS LOG (1/M) 8 0 30 LOG (1/M) 8 10 025077 BANDWIDTH CORRECTION COEFFICIENT 1 FOR ATOVS NUMERIC 5 -100000 18 NUMERIC 5 7 025078 BANDWIDTH CORRECTION COEFFICIENT 2 FOR ATOVS NUMERIC 5 0 17 NUMERIC 5 6 025079 ALBEDO-RADIANCE SOLAR FILTERED IRRADIANCE FOR ATOVS W/M**2 4 0 24 W/M**2 4 8 025080 ALBEDO-RADIANCE EQUIVALENT FILTER WIDTH FOR ATOVS M 10 0 14 M 10 5 025085 FRACTION OF CLEAR PIXELS IN HIRS FOV NUMERIC 0 0 7 NUMERIC 0 3 025086 DEPTH CORRECTION INDICATOR CODE TABLE 25086 0 0 2 CODE TABLE 25086 0 1 025091 STRUCTURE CONSTANT OF THE REFRACTION INDEX (CN2) dB 3 -18192 13 dB 3 5 025092 ACOUSTIC PROPAGATION VELOCITY M/S 2 28000 14 M/S 2 5 025093 RASS COMPUTATION CORRECTION FLAG TABLE 25093 0 0 8 FLAG TABLE 25093 0 3 025095 ALTIMETER STATE FLAG FLAG TABLE 25095 0 0 2 FLAG TABLE 25095 0 1 025096 RADIOMETER STATE FLAG FLAG TABLE 25096 0 0 5 FLAG TABLE 25096 0 2 025097 THREE DIMENSIONAL ERROR ESTIMATE OF THE NAVIGATOR ORBIT CODE TABLE 25097 0 0 4 CODE TABLE 25097 0 2 025100 XBT/XCTD FALL RATE EQUATION COEFFICIENT A NUMERIC 5 0 20 NUMERIC 5 6 025101 XBT/XCTD FALL RATE EQUATION COEFFICIENT B NUMERIC 5 -500000 21 NUMERIC 5 6 026001 PRINCIPAL TIME OF DAILY READING IN UTC OF MAXIMUM TEMPERATURE HOUR 1 0 12 HOUR 1 3 026002 PRINCIPAL TIME OF DAILY READING IN UTC OF MINIMUM TEMPERATURE HOUR 1 0 12 HOUR 1 3 026003 TIME DIFFERENCE MINUTE 0 -1440 12 MINUTE 0 4 026010 HOURS INCLUDED FLAG TABLE 26010 0 0 26 FLAG TABLE 26010 0 9 026020 DURATION OF PRECIPITATION MINUTE 0 0 11 MINUTE 0 4 027001 LATITUDE (HIGH ACCURACY) DEGREE 5 -9000000 25 DEGREE 5 7 027002 LATITUDE (COARSE ACCURACY) DEGREE 2 -9000 15 DEGREE 2 4 027003 ALTERNATE LATITUDE (COARSE ACCURACY) DEGREE 2 -9000 15 DEGREE 2 4 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 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 EARTH'S CENTRE M 2 -1073741824 31 M 2 10 029001 PROJECTION TYPE CODE TABLE 29001 0 0 3 CODE TABLE 29001 0 1 029002 CO-ORDINATE GRID TYPE CODE TABLE 29002 0 0 3 CODE TABLE 29002 0 1 030001 PIXEL VALUE (4 BITS) NUMERIC 0 0 4 NUMERIC 0 2 030002 PIXEL VALUE (8 BITS) NUMERIC 0 0 8 NUMERIC 0 3 030004 PIXEL VALUE (16 BITS) NUMERIC 0 0 16 NUMERIC 0 5 030021 NUMBER OF PIXELS PER ROW NUMERIC 0 0 12 NUMERIC 0 4 030022 NUMBER OF PIXELS PER COLUMN NUMERIC 0 0 12 NUMERIC 0 4 030031 PICTURE TYPE CODE TABLE 30031 0 0 4 CODE TABLE 30031 0 2 030032 COMBINATION WITH OTHER DATA FLAG TABLE 30032 0 0 16 FLAG TABLE 30032 0 6 031000 SHORT DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 1 NUMERIC 0 1 031001 DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031011 DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 8 NUMERIC 0 3 031012 EXTENDED DELAYED DESCRIPTOR AND DATA REPETITION FACTOR NUMERIC 0 0 16 NUMERIC 0 5 031021 ASSOCIATED FIELD SIGNIFICANCE CODE TABLE 31021 0 0 6 CODE TABLE 31021 0 2 031031 DATA PRESENT INDICATOR FLAG TABLE 31031 0 0 1 FLAG TABLE 31031 0 1 033002 QUALITY INFORMATION CODE TABLE 33002 0 0 2 CODE TABLE 33002 0 1 033003 QUALITY INFORMATION CODE TABLE 33003 0 0 3 CODE TABLE 33003 0 1 033005 QUALITY INFORMATION (AWS DATA) FLAG TABLE 33005 0 0 30 FLAG TABLE 33005 0 10 033006 INTERNAL MEASUREMENT STATUS INFORMATION (AWS) CODE TABLE 33006 0 0 3 CODE TABLE 33006 0 1 033007 PER CENT CONFIDENCE % 0 0 7 % 0 3 033015 DATA QUALITY CHECK INDICATOR CODE TABLE 33015 0 0 6 CODE TABLE 33015 0 2 033020 QUALITY CONTROL INDICATION OF FOLLOWING VALUE CODE TABLE 33020 0 0 3 CODE TABLE 33020 0 1 033021 QUALITY OF FOLLOWING VALUE CODE TABLE 33021 0 0 2 CODE TABLE 33021 0 1 033022 QUALITY OF BUOY SATELLITE TRANSMISSION CODE TABLE 33022 0 0 2 CODE TABLE 33022 0 1 033023 QUALITY OF BUOY LOCATION CODE TABLE 33023 0 0 2 CODE TABLE 33023 0 1 033024 STATION ELEVATION QUALITY MARK (FOR MOBILE STATIONS) CODE TABLE 33024 0 0 4 CODE TABLE 33024 0 2 033025 ACARS INTERPOLATED VALUES CODE TABLE 33025 0 0 3 CODE TABLE 33025 0 1 033026 MOISTURE QUALITY CODE TABLE 33026 0 0 6 CODE TABLE 33026 0 2 033027 LOCATION QUALITY CLASS (RANGE OF RADIUS OF 66 % CONFIDENCE) CODE TABLE 33027 0 0 3 CODE TABLE 33027 0 1 033030 SCAN LINE STATUS FLAGS FOR ATOVS FLAG TABLE 33030 0 0 24 FLAG TABLE 33030 0 8 033031 SCAN LINE QUALITY FLAGS FOR ATOVS FLAG TABLE 33031 0 0 24 FLAG TABLE 33031 0 8 033032 CHANNEL QUALITY FLAGS FOR ATOVS FLAG TABLE 33032 0 0 24 FLAG TABLE 33032 0 8 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS FLAG TABLE 33033 0 0 24 FLAG TABLE 33033 0 8 033035 MANUAL/AUTOMATIC QUALITY CONTROL CODE TABLE 33035 0 0 4 CODE TABLE 33035 0 2 033036 NOMINAL CONFIDENCE THRESHOLD % 0 0 7 % 0 3 033037 WIND CORRELATION ERROR FLAG TABLE 33037 0 0 20 FLAG TABLE 33037 0 7 033038 QUALITY FLAGS FOR GROUND-BASED GNSS DATA FLAG TABLE 33038 0 0 10 FLAG TABLE 33038 0 4 033040 CONFIDENCE INTERVAL % 0 0 7 PERCENT 0 3 033041 ATTRIBUTE OF FOLLOWING VALUE CODE TABLE 33041 0 0 2 CODE TABLE 33041 0 1 033050 GLOBAL GTSPP QUALITY FLAG CODE TABLE 33050 0 0 4 CODE TABLE 33050 0 2 035000 FM AND REGIONAL CODE NUMBER CODE TABLE 35000 0 0 10 CODE TABLE 35000 0 3 035001 TIME-FRAME FOR MONITORING CODE TABLE 35001 0 0 3 CODE TABLE 35001 0 1 035011 NUMBER OF REPORTS ACTUALLY RECEIVED NUMERIC 0 0 14 NUMERIC 0 4 035021 BULLETIN BEING MONITORED (TTAAII) CCITTIA5 0 0 48 CHARACTER 0 6 035022 BULLETIN BEING MONITORED (YYGGGG) CCITTIA5 0 0 48 CHARACTER 0 6 035023 BULLETIN BEING MONITORED (CCCC) CCITTIA5 0 0 32 CHARACTER 0 4 035024 BULLETIN BEING MONITORED (BBB) CCITTIA5 0 0 24 CHARACTER 0 3 035030 DISCREPANCIES IN THE AVAILABILITY OF EXPECTED DATA CODE TABLE 35030 0 0 4 CODE TABLE 35030 0 1 035031 QUALIFIER ON MONITORING RESULTS CODE TABLE 35031 0 0 7 CODE TABLE 35031 0 2 035032 CAUSE OF MISSING DATA CODE TABLE 35032 0 0 4 CODE TABLE 35032 0 1 035033 OBSERVATION AND COLLECTION DEFICIENCIES CODE TABLE 35033 0 0 7 CODE TABLE 35033 0 2 035034 STATISTICAL TRENDS FOR AVAILABILITY OF DATA (DURING THE SURVEY P CODE TABLE 35034 0 0 3 CODE TABLE 35034 0 1 035035 REASON FOR TERMINATION CODE TABLE 35035 0 0 5 CODE TABLE 35035 0 2 dballe-7.7/extra/test-repinfo2.csv0000644000175000017500000000031512652630043014074 0000000000000001,synop,report synottico,101,oss,0 201,FIXspnpo,FIX experiment,200,pre,255 210,LCBspnpo,LCB experiment,210,pre,255 220,MODspnpo,MOD experiment,220,pre,255 255,generic,export generici da DB Meteo,-5,?,255 dballe-7.7/extra/csv/0000755000175000017500000000000012652630043011532 500000000000000dballe-7.7/extra/csv/temp1.csv0000644000175000017500000005475212652630043013232 00000000000000Longitude,Latitude,Report,Date,Level1,L1,Level2,L2,Time range,P1,P2,Varcode,Value 9.2833,45.444,temp,2011-01-24 00:00:00,1,,,,254,0,0,B10004,100700 9.2833,45.444,temp,2011-01-24 00:00:00,100,770,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,770,0,5,254,0,0,B12101,228.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,770,0,5,254,0,0,B12103,192.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,1000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,1000,0,2,254,0,0,B10008,302999 9.2833,45.444,temp,2011-01-24 00:00:00,100,1000,0,2,254,0,0,B11001,145 9.2833,45.444,temp,2011-01-24 00:00:00,100,1000,0,2,254,0,0,B11002,9.8 9.2833,45.444,temp,2011-01-24 00:00:00,100,1000,0,2,254,0,0,B12101,229.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,1000,0,2,254,0,0,B12103,193.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,1110,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,1110,0,6,254,0,0,B11001,140 9.2833,45.444,temp,2011-01-24 00:00:00,100,1110,0,6,254,0,0,B11002,6.7 9.2833,45.444,temp,2011-01-24 00:00:00,100,1190,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,1190,0,6,254,0,0,B11001,165 9.2833,45.444,temp,2011-01-24 00:00:00,100,1190,0,6,254,0,0,B11002,9.3 9.2833,45.444,temp,2011-01-24 00:00:00,100,1350,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,1350,0,6,254,0,0,B11001,120 9.2833,45.444,temp,2011-01-24 00:00:00,100,1350,0,6,254,0,0,B11002,8.2 9.2833,45.444,temp,2011-01-24 00:00:00,100,1450,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,1450,0,6,254,0,0,B11001,150 9.2833,45.444,temp,2011-01-24 00:00:00,100,1450,0,6,254,0,0,B11002,10.8 9.2833,45.444,temp,2011-01-24 00:00:00,100,1570,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,1570,0,6,254,0,0,B11001,145 9.2833,45.444,temp,2011-01-24 00:00:00,100,1570,0,6,254,0,0,B11002,10.8 9.2833,45.444,temp,2011-01-24 00:00:00,100,1630,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,1630,0,5,254,0,0,B12101,227.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,1630,0,5,254,0,0,B12103,192.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,1670,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,1670,0,6,254,0,0,B11001,135 9.2833,45.444,temp,2011-01-24 00:00:00,100,1670,0,6,254,0,0,B11002,7.7 9.2833,45.444,temp,2011-01-24 00:00:00,100,1840,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,1840,0,6,254,0,0,B11001,140 9.2833,45.444,temp,2011-01-24 00:00:00,100,1840,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,1850,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,1850,0,5,254,0,0,B12101,222.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,1850,0,5,254,0,0,B12103,188.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,2000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,2000,0,2,254,0,0,B10008,257765 9.2833,45.444,temp,2011-01-24 00:00:00,100,2000,0,2,254,0,0,B11001,70 9.2833,45.444,temp,2011-01-24 00:00:00,100,2000,0,2,254,0,0,B11002,4.6 9.2833,45.444,temp,2011-01-24 00:00:00,100,2000,0,2,254,0,0,B12101,223.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,2000,0,2,254,0,0,B12103,189.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,2210,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,2210,0,6,254,0,0,B11001,115 9.2833,45.444,temp,2011-01-24 00:00:00,100,2210,0,6,254,0,0,B11002,1.0 9.2833,45.444,temp,2011-01-24 00:00:00,100,2230,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,2230,0,5,254,0,0,B12101,224.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,2230,0,5,254,0,0,B12103,190.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,2620,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,2620,0,5,254,0,0,B12101,219.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,2620,0,5,254,0,0,B12103,186.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,3000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,3000,0,2,254,0,0,B10008,231959 9.2833,45.444,temp,2011-01-24 00:00:00,100,3000,0,2,254,0,0,B11001,105 9.2833,45.444,temp,2011-01-24 00:00:00,100,3000,0,2,254,0,0,B11002,1.5 9.2833,45.444,temp,2011-01-24 00:00:00,100,3000,0,2,254,0,0,B12101,222.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,3000,0,2,254,0,0,B12103,188.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,3060,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,3060,0,5,254,0,0,B12101,222.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,3060,0,5,254,0,0,B12103,188.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,3260,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,3260,0,6,254,0,0,B11001,10 9.2833,45.444,temp,2011-01-24 00:00:00,100,3260,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,3510,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,3510,0,6,254,0,0,B11001,25 9.2833,45.444,temp,2011-01-24 00:00:00,100,3510,0,6,254,0,0,B11002,7.7 9.2833,45.444,temp,2011-01-24 00:00:00,100,3690,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,3690,0,6,254,0,0,B11001,360 9.2833,45.444,temp,2011-01-24 00:00:00,100,3690,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,4030,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,4030,0,5,254,0,0,B12101,217.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,4030,0,5,254,0,0,B12103,185.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,4320,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,4320,0,6,254,0,0,B11001,15 9.2833,45.444,temp,2011-01-24 00:00:00,100,4320,0,6,254,0,0,B11002,1.5 9.2833,45.444,temp,2011-01-24 00:00:00,100,5000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,5000,0,2,254,0,0,B10008,199775 9.2833,45.444,temp,2011-01-24 00:00:00,100,5000,0,2,254,0,0,B11001,320 9.2833,45.444,temp,2011-01-24 00:00:00,100,5000,0,2,254,0,0,B11002,4.6 9.2833,45.444,temp,2011-01-24 00:00:00,100,5000,0,2,254,0,0,B12101,219.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,5000,0,2,254,0,0,B12103,186.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,5070,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,5070,0,5,254,0,0,B12101,219.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,5070,0,5,254,0,0,B12103,186.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,7000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,7000,0,2,254,0,0,B10008,178679 9.2833,45.444,temp,2011-01-24 00:00:00,100,7000,0,2,254,0,0,B11001,350 9.2833,45.444,temp,2011-01-24 00:00:00,100,7000,0,2,254,0,0,B11002,3.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,7000,0,2,254,0,0,B12101,218.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,7000,0,2,254,0,0,B12103,186.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,7240,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,7240,0,6,254,0,0,B11001,335 9.2833,45.444,temp,2011-01-24 00:00:00,100,7240,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,7500,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,7500,0,6,254,0,0,B11001,305 9.2833,45.444,temp,2011-01-24 00:00:00,100,7500,0,6,254,0,0,B11002,6.2 9.2833,45.444,temp,2011-01-24 00:00:00,100,7680,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,7680,0,6,254,0,0,B11001,305 9.2833,45.444,temp,2011-01-24 00:00:00,100,7680,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,2,254,0,0,B08042,38 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,2,254,0,0,B10008,156405 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,2,254,0,0,B11001,355 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,2,254,0,0,B11002,3.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,2,254,0,0,B12101,217.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,2,254,0,0,B12103,185.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,5,254,0,0,B08042,38 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,5,254,0,0,B12101,217.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,5,254,0,0,B12103,185.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,6,254,0,0,B08042,38 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,6,254,0,0,B11001,355 9.2833,45.444,temp,2011-01-24 00:00:00,100,10000,0,6,254,0,0,B11002,3.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,10900,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,10900,0,6,254,0,0,B11001,15 9.2833,45.444,temp,2011-01-24 00:00:00,100,10900,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,11400,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,11400,0,5,254,0,0,B12101,219.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,11400,0,5,254,0,0,B12103,186.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,12900,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,12900,0,6,254,0,0,B11001,340 9.2833,45.444,temp,2011-01-24 00:00:00,100,12900,0,6,254,0,0,B11002,5.7 9.2833,45.444,temp,2011-01-24 00:00:00,100,14100,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,14100,0,6,254,0,0,B11001,25 9.2833,45.444,temp,2011-01-24 00:00:00,100,14100,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,14900,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,14900,0,6,254,0,0,B11001,20 9.2833,45.444,temp,2011-01-24 00:00:00,100,14900,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,15000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,15000,0,2,254,0,0,B10008,130894 9.2833,45.444,temp,2011-01-24 00:00:00,100,15000,0,2,254,0,0,B11001,20 9.2833,45.444,temp,2011-01-24 00:00:00,100,15000,0,2,254,0,0,B11002,5.7 9.2833,45.444,temp,2011-01-24 00:00:00,100,15000,0,2,254,0,0,B12101,219.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,15000,0,2,254,0,0,B12103,186.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,16000,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,16000,0,6,254,0,0,B11001,40 9.2833,45.444,temp,2011-01-24 00:00:00,100,16000,0,6,254,0,0,B11002,8.2 9.2833,45.444,temp,2011-01-24 00:00:00,100,17400,0,5,254,0,0,B08042,6 9.2833,45.444,temp,2011-01-24 00:00:00,100,17400,0,5,254,0,0,B12101,216.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,17400,0,5,254,0,0,B12103,186.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,17400,0,6,254,0,0,B08042,6 9.2833,45.444,temp,2011-01-24 00:00:00,100,17400,0,6,254,0,0,B11001,15 9.2833,45.444,temp,2011-01-24 00:00:00,100,17400,0,6,254,0,0,B11002,14.9 9.2833,45.444,temp,2011-01-24 00:00:00,100,20000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,20000,0,2,254,0,0,B10008,112938 9.2833,45.444,temp,2011-01-24 00:00:00,100,20000,0,2,254,0,0,B11001,25 9.2833,45.444,temp,2011-01-24 00:00:00,100,20000,0,2,254,0,0,B11002,13.4 9.2833,45.444,temp,2011-01-24 00:00:00,100,20000,0,2,254,0,0,B12101,217.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,20000,0,2,254,0,0,B12103,189.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,21100,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,21100,0,6,254,0,0,B11001,20 9.2833,45.444,temp,2011-01-24 00:00:00,100,21100,0,6,254,0,0,B11002,11.8 9.2833,45.444,temp,2011-01-24 00:00:00,100,21400,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,21400,0,5,254,0,0,B12101,218.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,21400,0,5,254,0,0,B12103,193.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,23100,0,3,254,0,0,B08042,20 9.2833,45.444,temp,2011-01-24 00:00:00,100,23100,0,3,254,0,0,B11001,40 9.2833,45.444,temp,2011-01-24 00:00:00,100,23100,0,3,254,0,0,B11002,17.0 9.2833,45.444,temp,2011-01-24 00:00:00,100,23100,0,3,254,0,0,B12101,214.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,23100,0,3,254,0,0,B12103,197.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,23100,0,5,254,0,0,B08042,20 9.2833,45.444,temp,2011-01-24 00:00:00,100,23100,0,5,254,0,0,B12101,214.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,23100,0,5,254,0,0,B12103,197.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,24500,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,24500,0,6,254,0,0,B11001,55 9.2833,45.444,temp,2011-01-24 00:00:00,100,24500,0,6,254,0,0,B11002,17.5 9.2833,45.444,temp,2011-01-24 00:00:00,100,25000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,25000,0,2,254,0,0,B10008,99004 9.2833,45.444,temp,2011-01-24 00:00:00,100,25000,0,2,254,0,0,B11001,55 9.2833,45.444,temp,2011-01-24 00:00:00,100,25000,0,2,254,0,0,B11002,19.5 9.2833,45.444,temp,2011-01-24 00:00:00,100,25000,0,2,254,0,0,B12101,217.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,25000,0,2,254,0,0,B12103,200.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,28300,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,28300,0,6,254,0,0,B11001,50 9.2833,45.444,temp,2011-01-24 00:00:00,100,28300,0,6,254,0,0,B11002,37.0 9.2833,45.444,temp,2011-01-24 00:00:00,100,29500,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,29500,0,5,254,0,0,B12101,219.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,29500,0,5,254,0,0,B12103,203.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,30000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,30000,0,2,254,0,0,B10008,87622 9.2833,45.444,temp,2011-01-24 00:00:00,100,30000,0,2,254,0,0,B11001,45 9.2833,45.444,temp,2011-01-24 00:00:00,100,30000,0,2,254,0,0,B11002,35.5 9.2833,45.444,temp,2011-01-24 00:00:00,100,30000,0,2,254,0,0,B12101,220.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,30000,0,2,254,0,0,B12103,202.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,31000,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,31000,0,5,254,0,0,B12101,221.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,31000,0,5,254,0,0,B12103,202.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,32900,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,32900,0,6,254,0,0,B11001,55 9.2833,45.444,temp,2011-01-24 00:00:00,100,32900,0,6,254,0,0,B11002,30.4 9.2833,45.444,temp,2011-01-24 00:00:00,100,34800,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,34800,0,5,254,0,0,B12101,225.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,34800,0,5,254,0,0,B12103,216.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,36000,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,36000,0,6,254,0,0,B11001,60 9.2833,45.444,temp,2011-01-24 00:00:00,100,36000,0,6,254,0,0,B11002,35.5 9.2833,45.444,temp,2011-01-24 00:00:00,100,39700,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,39700,0,5,254,0,0,B12101,233.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,39700,0,5,254,0,0,B12103,217.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,40000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,40000,0,2,254,0,0,B10008,68881 9.2833,45.444,temp,2011-01-24 00:00:00,100,40000,0,2,254,0,0,B11001,60 9.2833,45.444,temp,2011-01-24 00:00:00,100,40000,0,2,254,0,0,B11002,31.4 9.2833,45.444,temp,2011-01-24 00:00:00,100,40000,0,2,254,0,0,B12101,233.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,40000,0,2,254,0,0,B12103,219.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,40200,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,40200,0,5,254,0,0,B12101,233.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,40200,0,5,254,0,0,B12103,220.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,45500,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,45500,0,5,254,0,0,B12101,239.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,45500,0,5,254,0,0,B12103,222.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,46400,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,46400,0,5,254,0,0,B12101,240.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,46400,0,5,254,0,0,B12103,230.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,48800,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,48800,0,6,254,0,0,B11001,55 9.2833,45.444,temp,2011-01-24 00:00:00,100,48800,0,6,254,0,0,B11002,17.0 9.2833,45.444,temp,2011-01-24 00:00:00,100,50000,0,2,254,0,0,B08042,36 9.2833,45.444,temp,2011-01-24 00:00:00,100,50000,0,2,254,0,0,B10008,53574 9.2833,45.444,temp,2011-01-24 00:00:00,100,50000,0,2,254,0,0,B11001,50 9.2833,45.444,temp,2011-01-24 00:00:00,100,50000,0,2,254,0,0,B11002,15.4 9.2833,45.444,temp,2011-01-24 00:00:00,100,50000,0,2,254,0,0,B12101,244.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,50000,0,2,254,0,0,B12103,232.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,50000,0,5,254,0,0,B08042,36 9.2833,45.444,temp,2011-01-24 00:00:00,100,50000,0,5,254,0,0,B12101,244.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,50000,0,5,254,0,0,B12103,231.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,53800,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,53800,0,6,254,0,0,B11001,40 9.2833,45.444,temp,2011-01-24 00:00:00,100,53800,0,6,254,0,0,B11002,10.3 9.2833,45.444,temp,2011-01-24 00:00:00,100,54300,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,54300,0,5,254,0,0,B12101,248.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,54300,0,5,254,0,0,B12103,241.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,57600,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,57600,0,5,254,0,0,B12101,250.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,57600,0,5,254,0,0,B12103,246.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,60000,0,7,254,0,0,B08042,1 9.2833,45.444,temp,2011-01-24 00:00:00,100,60000,0,7,254,0,0,B11001,40 9.2833,45.444,temp,2011-01-24 00:00:00,100,60000,0,7,254,0,0,B11002,8.7 9.2833,45.444,temp,2011-01-24 00:00:00,100,62800,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,62800,0,5,254,0,0,B12101,254.06 9.2833,45.444,temp,2011-01-24 00:00:00,100,62800,0,5,254,0,0,B12103,250.56 9.2833,45.444,temp,2011-01-24 00:00:00,100,64800,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,64800,0,6,254,0,0,B11001,45 9.2833,45.444,temp,2011-01-24 00:00:00,100,64800,0,6,254,0,0,B11002,8.2 9.2833,45.444,temp,2011-01-24 00:00:00,100,68400,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,68400,0,5,254,0,0,B12101,259.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,68400,0,5,254,0,0,B12103,247.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,69500,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,69500,0,6,254,0,0,B11001,60 9.2833,45.444,temp,2011-01-24 00:00:00,100,69500,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,70000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,70000,0,2,254,0,0,B10008,29230 9.2833,45.444,temp,2011-01-24 00:00:00,100,70000,0,2,254,0,0,B11001,60 9.2833,45.444,temp,2011-01-24 00:00:00,100,70000,0,2,254,0,0,B11002,4.6 9.2833,45.444,temp,2011-01-24 00:00:00,100,70000,0,2,254,0,0,B12101,260.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,70000,0,2,254,0,0,B12103,248.46 9.2833,45.444,temp,2011-01-24 00:00:00,100,76400,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,76400,0,5,254,0,0,B12101,266.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,76400,0,5,254,0,0,B12103,248.26 9.2833,45.444,temp,2011-01-24 00:00:00,100,80000,0,7,254,0,0,B08042,1 9.2833,45.444,temp,2011-01-24 00:00:00,100,80000,0,7,254,0,0,B11001,5 9.2833,45.444,temp,2011-01-24 00:00:00,100,80000,0,7,254,0,0,B11002,3.6 9.2833,45.444,temp,2011-01-24 00:00:00,100,85000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,85000,0,2,254,0,0,B10008,14375 9.2833,45.444,temp,2011-01-24 00:00:00,100,85000,0,2,254,0,0,B11001,255 9.2833,45.444,temp,2011-01-24 00:00:00,100,85000,0,2,254,0,0,B11002,2.6 9.2833,45.444,temp,2011-01-24 00:00:00,100,85000,0,2,254,0,0,B12101,270.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,85000,0,2,254,0,0,B12103,247.86 9.2833,45.444,temp,2011-01-24 00:00:00,100,88500,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,88500,0,5,254,0,0,B12101,272.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,88500,0,5,254,0,0,B12103,245.66 9.2833,45.444,temp,2011-01-24 00:00:00,100,88900,0,7,254,0,0,B08042,1 9.2833,45.444,temp,2011-01-24 00:00:00,100,88900,0,7,254,0,0,B11001,230 9.2833,45.444,temp,2011-01-24 00:00:00,100,88900,0,7,254,0,0,B11002,3.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,90700,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,90700,0,5,254,0,0,B12101,274.16 9.2833,45.444,temp,2011-01-24 00:00:00,100,90700,0,5,254,0,0,B12103,254.16 9.2833,45.444,temp,2011-01-24 00:00:00,100,91300,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,91300,0,5,254,0,0,B12101,273.16 9.2833,45.444,temp,2011-01-24 00:00:00,100,91300,0,5,254,0,0,B12103,262.16 9.2833,45.444,temp,2011-01-24 00:00:00,100,96000,0,6,254,0,0,B08042,2 9.2833,45.444,temp,2011-01-24 00:00:00,100,96000,0,6,254,0,0,B11001,275 9.2833,45.444,temp,2011-01-24 00:00:00,100,96000,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,96400,0,5,254,0,0,B08042,4 9.2833,45.444,temp,2011-01-24 00:00:00,100,96400,0,5,254,0,0,B12101,274.56 9.2833,45.444,temp,2011-01-24 00:00:00,100,96400,0,5,254,0,0,B12103,262.56 9.2833,45.444,temp,2011-01-24 00:00:00,100,99500,0,5,254,0,0,B08042,6 9.2833,45.444,temp,2011-01-24 00:00:00,100,99500,0,5,254,0,0,B12101,274.76 9.2833,45.444,temp,2011-01-24 00:00:00,100,99500,0,5,254,0,0,B12103,268.76 9.2833,45.444,temp,2011-01-24 00:00:00,100,99500,0,6,254,0,0,B08042,6 9.2833,45.444,temp,2011-01-24 00:00:00,100,99500,0,6,254,0,0,B11001,280 9.2833,45.444,temp,2011-01-24 00:00:00,100,99500,0,6,254,0,0,B11002,5.1 9.2833,45.444,temp,2011-01-24 00:00:00,100,100000,0,2,254,0,0,B08042,32 9.2833,45.444,temp,2011-01-24 00:00:00,100,100000,0,2,254,0,0,B10008,1599 9.2833,45.444,temp,2011-01-24 00:00:00,100,100000,0,2,254,0,0,B11001,270 9.2833,45.444,temp,2011-01-24 00:00:00,100,100000,0,2,254,0,0,B11002,3.6 9.2833,45.444,temp,2011-01-24 00:00:00,100,100000,0,2,254,0,0,B12101,274.36 9.2833,45.444,temp,2011-01-24 00:00:00,100,100000,0,2,254,0,0,B12103,269.56 9.2833,45.444,temp,2011-01-24 00:00:00,100,100700,0,1,254,0,0,B08042,64 9.2833,45.444,temp,2011-01-24 00:00:00,100,100700,0,1,254,0,0,B11001,250 9.2833,45.444,temp,2011-01-24 00:00:00,100,100700,0,1,254,0,0,B11002,1.0 9.2833,45.444,temp,2011-01-24 00:00:00,100,100700,0,1,254,0,0,B12101,273.56 9.2833,45.444,temp,2011-01-24 00:00:00,100,100700,0,1,254,0,0,B12103,269.56 9.2833,45.444,temp,2011-01-24 00:00:00,103,2000,,,254,0,0,B12101,273.56 9.2833,45.444,temp,2011-01-24 00:00:00,103,2000,,,254,0,0,B12103,269.56 9.2833,45.444,temp,2011-01-24 00:00:00,103,10000,,,254,0,0,B11001,250 9.2833,45.444,temp,2011-01-24 00:00:00,103,10000,,,254,0,0,B11002,2.0 9.2833,45.444,temp,2011-01-24 00:00:00,256,,258,0,254,0,0,B20011,0 9.2833,45.444,temp,2011-01-24 00:00:00,256,,258,0,254,0,0,B20013,2500 9.2833,45.444,temp,2011-01-24 00:00:00,256,,258,1,254,0,0,B20012,30 9.2833,45.444,temp,2011-01-24 00:00:00,256,,258,2,254,0,0,B20012,30 9.2833,45.444,temp,2011-01-24 00:00:00,256,,258,3,254,0,0,B20012,30 9.2833,45.444,temp,,,,,,,,,B01001,16 9.2833,45.444,temp,,,,,,,,,B01002,80 9.2833,45.444,temp,,,,,,,,,B01194,temp 9.2833,45.444,temp,,,,,,,,,B04001,2011 9.2833,45.444,temp,,,,,,,,,B04002,1 9.2833,45.444,temp,,,,,,,,,B04003,24 9.2833,45.444,temp,,,,,,,,,B04004,0 9.2833,45.444,temp,,,,,,,,,B04005,0 9.2833,45.444,temp,,,,,,,,,B04006,0 9.2833,45.444,temp,,,,,,,,,B05001,45.44442 9.2833,45.444,temp,,,,,,,,,B06001,9.28333 9.2833,45.444,temp,,,,,,,,,B07030,102.0 9.2833,45.444,temp,,,,,,,,,B07031,103.0 dballe-7.7/extra/runtest0000755000175000017500000000260512652630043012314 00000000000000#!/bin/bash set -e # Limit to 1G of virtual memory ulimit -v 1000000 TOP_SRCDIR=`pwd`/`dirname $0`/.. PYTHON=${PYTHON:-python} CMD=`pwd`/"$1" ## Set up the test environment export WREPORT_EXTRA_TABLES=$TOP_SRCDIR/tables export WREPORT_TESTDATA=$TOP_SRCDIR/extra export DBA_REPINFO=$TOP_SRCDIR/tables/repinfo.csv export DBA_TABLES=$TOP_SRCDIR/tables export DBA_TESTDATA=$TOP_SRCDIR/extra export DBA_INSECURE_SQLITE=1 TESTDIR="`mktemp -d`" cd "$TESTDIR" touch test.sqlite ## Clean up the test environment at exit unless asked otherwise cleanup() { if [ ! -z "$PAUSE" ] then echo "Post-test inspection requested." echo "Exit this shell to cleanup the test environment." bash fi test -z "$PRESERVE" && rm -rf "$TESTDIR" } trap cleanup EXIT #id=`date +%y%m%d%H%M%S` #$DEBUGGER $BIN $ARGS 2>&1 | tee `pwd`/testrun-$id #echo Output saved in `pwd`/testrun-$id # Try to debug the libtool executable, if present DIR=`dirname $CMD` BASE=`basename $CMD` if [ "${BASE##*.}" = "py" ] then CMD="$PYTHON $CMD" fi if [ ! -z "$DEBUGGER" ] then if [ -x $DIR/.libs/lt-$BASE ] 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 echo "Running $CMD $ARGS" RES=0 if ! $CMD $ARGS then RES=$? echo "Failed with result $RES" fi fi exit $RES dballe-7.7/extra/crex/0000755000175000017500000000000012652630043011700 500000000000000dballe-7.7/extra/crex/test-synop1.crex0000644000175000017500000000025012652630043014706 00000000000000CREX++ T000103 A000 D01031 R02005 B07061 B12030++ 10 280 1 2004 11 30 12 00 5355000 01320000 00080 00005 046 00010 042 00020 041 00050 053 00100 066++ 7777 dballe-7.7/extra/crex/test-synop2.crex0000644000175000017500000000041212652630043014707 00000000000000CREX++ T000103 A000 D07005 B13023 B13013++ 10 954 1 2004 11 30 12 00 4783000 01087000 00757 09201 ///// -0021 07 070 0060 017 008 /// 0450 010 02 02 100 01 08 0015 36 61 60 01 08 07 0017 02 // // //// 03 // // //// // // // //// ///// /////++ 7777 dballe-7.7/extra/crex/test-synop3.crex0000644000175000017500000000045112652630043014713 00000000000000CREX++ T000103 A000 D01031 B12013 B12017 B12016 B13031 B14015 B14031 B20062 B20192 B20192 B20192 B20192 B11233 B11041 B11230 B11231 B11232++ 02 945 1 2004 11 30 12 00 6185000 02480000 00145 /// /// /// /// ///// //// // ///// ///// ///// ///// //// //// //// //// ////++ 7777 dballe-7.7/extra/crex/test-temp0.crex0000644000175000017500000000562112652630043014511 00000000000000CREX++ T000103 A002 D09007 R04000 B07004 B08001 B11061 B11062 ++ 06 181 071 04 2004 11 30 12 00 5575000 01252000 00040 /// 01 // //// // // // 0075 10130 106 000039 062 023 215 0020 10000 040 000143 052 008 225 0050 09710 004 000378 032 -028 /// //// 09600 002 ////// /// /// 235 0070 09250 040 000762 -003 -035 240 0070 08790 004 001158 -043 -044 /// //// 08630 004 001300 -053 -054 /// //// 08600 004 001327 -057 -117 /// //// 08570 004 001354 -029 -179 /// //// 08530 004 001390 000 -190 /// //// 08500 040 001419 004 -226 245 0070 08340 004 001567 006 -244 /// //// 07590 004 002307 002 -178 /// //// 07000 040 002939 -033 -243 260 0120 06970 002 ////// /// /// 260 0120 06460 002 ////// /// /// 260 0090 06150 004 003931 -091 -211 /// //// 06010 004 004105 -097 -257 /// //// 05680 002 ////// /// /// 230 0110 05460 004 004823 -153 -343 /// //// 05370 002 ////// /// /// 240 0090 05000 040 005472 -207 -297 275 0070 04930 002 ////// /// /// 280 0070 04900 004 005614 -219 -329 /// //// 04800 002 ////// /// /// 290 0070 04510 004 006207 -263 -309 /// //// 04300 004 006544 -287 -367 /// //// 04050 002 ////// /// /// 295 0090 04000 040 007051 -333 -383 295 0090 03560 002 ////// /// /// 325 0090 03500 004 007952 -409 -447 /// //// 03180 004 008584 -463 -505 /// //// 03000 040 008963 -493 -529 330 0150 02500 040 010120 -565 -625 335 0200 02420 004 010315 -583 -643 /// //// 02000 040 011474 -673 -722 330 0210 01990 002 ////// /// /// 330 0210 01970 004 011555 -681 -729 /// //// 01810 024 012051 -697 -738 325 0200 01500 040 013170 -655 -765 325 0160 01490 004 013202 -647 -757 /// //// 01400 004 013574 -649 -789 /// //// 01180 004 014598 -641 -821 /// //// 01170 002 ////// /// /// 315 0110 01100 004 015017 -663 -853 /// //// 01000 042 015593 -631 -841 335 0110 00906 002 ////// /// /// 305 0120 00831 002 ////// /// /// 330 0190 00795 002 ////// /// /// 340 0180 00714 002 ////// /// /// 330 0160 00700 040 017711 -693 -893 330 0160 00685 024 017806 -697 -887 330 0160 00640 004 018205 -677 -887 /// //// 00599 002 ////// /// /// 335 0130 00500 040 019682 -695 -885 340 0150 00385 004 021178 -709 -899 /// //// 00377 002 ////// /// /// 345 0150 00318 002 ////// /// /// 340 0200 00300 040 022673 -697 -907 335 0190 00274 004 023162 -689 -899 /// //// 00268 002 ////// /// /// 330 0150 00235 002 ////// /// /// 350 0160 00216 002 ////// /// /// 340 0160 00200 040 025036 -701 -911 335 0170 00175 002 ////// /// /// 325 0240 00170 004 025934 -727 -917 /// //// 00155 004 026469 -699 -909 /// //// 00138 002 ////// /// /// 325 0170 00104 004 028776 -737 -927 /// //// 00100 040 029037 -733 -923 325 0260 00090 004 029609 -709 -899 /// //// 00083 002 ////// /// /// 315 0310 00080 004 030290 -725 -915 /// //// 00070 012 ////// /// /// 330 0440 00068 004 031240 -663 -873 /// //// 0001 00070 010 0140 ////++ 7777 dballe-7.7/extra/crex/test-mare0.crex0000644000175000017500000000026412652630043014466 00000000000000CREX++ T000103 A001 D08003++ 44613 010 000 0 2004 11 30 12 00 6827 00968 ///// ///// //// // /// //// /// /// /// //// /// // // /// // // //// // // // 2809++ 7777 dballe-7.7/extra/crex/test-mare1.crex0000644000175000017500000000026512652630043014470 00000000000000CREX++ T000103 A001 D08003++ 44743 010 000 0 2004 11 30 12 00 4302 -01245 10084 10084 0016 07 /// //// /// /// /// //// /// // // /// // // //// // // // 2882++ 7777 dballe-7.7/extra/crex/old/0000755000175000017500000000000012652630043012456 500000000000000dballe-7.7/extra/crex/old/test-buoy.crex0000644000175000017500000000032712652630043015216 00000000000000CREX++ T000103 A001 D08003 E++ 148583 2/// 3/// 40 52003 611 725 815 910 08336 1-14709 2///// 310114 4//// 5// 6/// 7//// 8/// 9/// 0/// 1//// 2/// 3// 4// 5/// 6// 7// 8//// 9// 0// 1// 2////++ 7777 dballe-7.7/extra/crex/old/test-acar.crex0000644000175000017500000000055712652630043015153 00000000000000CREX++ T000103 A004 B01006 B01008 B02061 B02062 B02002 B02005 B02070 B02063 B02001 B04001 B04002 B04003 B04004 B04005 B05002 B06002 B08004 B07004 B08021 B11001 B11002 B11031 B11034 B11035 B12001 B12003 B13003 B20041++ 00001008 JEWEITRA / 03 04 025 10 ///// 0 2003 12 21 21 01 3400 -08501 / 06318 // 296 0093 // //// ///// -035 /// /// //++ 7777 dballe-7.7/extra/crex/old/test-synop-ship.crex0000644000175000017500000000036412652630043016352 00000000000000CREX++ T000103 A001 D08004 B12005 B10197 E++ 1000001009 2315 3009 41 52003 611 705 806 900 0-0800 1-00320 2///// 310134 40001 500 6150 70080 8220 9171 0/// 12000 2003 302 402 5090 601 707 80045 937 025 116 22948 3190 4///++ 7777 dballe-7.7/extra/crex/old/test-synop.crex0000644000175000017500000000047512652630043015414 00000000000000CREX++ T000103 A000 D07005 B13023 B13013 E++ 110 2033 31 42003 512 621 722 800 95483000 000950000 100033 209917 309958 40041 5// 6300 70100 8011 9-005 0/// 12500 2002 301 401 5025 601 702 80175 935 020 110 201 307 406 50152 602 7// 8// 9//// 003 1// 2// 3//// 4// 5// 6// 7//// 8///// 9/////++ 7777 dballe-7.7/extra/crex/old/test-buoy-baddigit.crex0000644000175000017500000000032712652630043016763 00000000000000CREX++ T000103 A001 D08003 E++ 148583 2/// 3/// 40 52003 611 725 815 910 08336 1-14709 2///// 310114 4//// 5// 6/// 1//// 8/// 9/// 0/// 1//// 2/// 3// 4// 5/// 6// 7// 8//// 9// 0// 1// 2////++ 7777 dballe-7.7/extra/crex/old/test-temp.crex0000644000175000017500000000466412652630043015215 00000000000000CREX++ T000103 A002 D09007 R04000 B07004 B08001 B11061 B11062 E++ 161 2052 3/// 4// 52003 612 721 822 900 01348000 100217000 200227 3/// 4// 5// 6//// 7// 8// 9// 00052 110000 2040 3000126 4/// 5/// 6/// 7//// 809890 9100 0000223 1234 2-046 3020 40020 509250 6040 7000792 8228 9-092 0065 10100 208500 3040 4001505 5184 6-216 7080 80060 907000 0040 1003114 2094 3-066 4225 50060 605000 7040 8005766 9-059 0-539 1145 20040 304000 4040 5007443 6-159 7-609 8280 90040 003000 1040 2009493 3-335 4-605 5345 60140 702500 8040 9010719 0-437 1/// 2305 30150 402000 5040 6012160 7-555 8/// 9280 00180 101500 2040 3013896 4-695 5/// 6250 70310 801420 9010 0////// 1/// 2/// 3260 40320 501000 6040 7016240 8-785 9/// 0265 10090 200970 3024 4////// 5-799 6/// 7245 80070 900943 0002 1////// 2/// 3/// 4240 50060 600882 7002 8////// 9/// 0/// 1325 20050 300839 4002 5////// 6/// 7/// 8035 90050 000817 1002 2////// 3/// 4/// 5105 60050 700799 8002 9////// 0/// 1/// 2145 30060 400768 5004 6////// 7-819 8/// 9/// 0//// 100700 2044 3018221 4-757 5/// 6215 70050 800668 9002 0////// 1/// 2/// 3245 40050 500615 6004 7////// 8-717 9/// 0/// 1//// 200586 3002 4////// 5/// 6/// 7150 80020 900575 0002 1////// 2/// 3/// 4055 50030 600539 7002 8////// 9/// 0/// 1065 20070 300511 4002 5////// 6/// 7/// 8120 90100 000500 1040 2020172 3-697 4/// 5115 60100 700494 8002 9////// 0/// 1/// 2110 30100 400474 5004 6////// 7-689 8/// 9/// 0//// 100470 2002 3////// 4/// 5/// 6130 70070 800444 9002 0////// 1/// 2/// 3100 40050 500424 6002 7////// 8/// 9/// 0055 10040 200422 3004 4////// 5-641 6/// 7/// 8//// 900412 0002 1////// 2/// 3/// 4035 50050 600388 7002 8////// 9/// 0/// 1045 20060 300386 4004 5////// 6-657 7/// 8/// 9//// 000369 1002 2////// 3/// 4/// 5075 60070 700356 8004 9////// 0-619 1/// 2/// 3//// 400352 5002 6////// 7/// 8/// 9070 00100 100335 2002 3////// 4/// 5/// 6090 70120 800316 9002 0////// 1/// 2/// 3105 40090 500300 6040 7023232 8-605 9/// 0095 10080 200297 3002 4////// 5/// 6/// 7085 80090 900294 0004 1////// 2-605 3/// 4/// 5//// 600287 7002 8////// 9/// 0/// 1105 20080 300263 4002 5////// 6/// 7/// 8070 90080 000254 1002 2////// 3/// 4/// 5075 60100 700239 8002 9////// 0/// 1/// 2040 30090 400222 5002 6////// 7/// 8/// 9090 00080 100209 2006 3////// 4-523 5/// 6080 70090 800200 9040 0025762 1/// 2/// 3/// 4//// 50001 601420 7010 80070 90220++ 7777 dballe-7.7/extra/crex/old/test-satob.crex0000644000175000017500000000077012652630043015352 00000000000000CREX++ T000103 A005 D01043 D04001++ 0254 01 2003 12 21 23 00 00 3990000 -08950000 02 02600 -495 285 0267+ 0254 01 2003 12 21 23 00 00 3990000 -08950000 02 02600 -495 280 0267+ 0254 01 2003 12 21 23 00 00 3960000 -08890000 02 03100 -395 285 0216+ 0254 01 2003 12 21 23 00 00 3980000 -08790000 02 02800 -473 285 0231+ 0254 01 2003 12 21 23 00 00 3850000 -08960000 02 02600 -511 290 0236+ 0254 01 2003 12 21 23 00 00 3830000 -08970000 02 02200 -519 290 0241++ 7777 dballe-7.7/extra/crex/old/test-amdar.crex0000644000175000017500000000020512652630043015317 00000000000000CREX++ T000103 A004 D11001++ 00001008 0 2003 11 05 00 00 3150500 01311833 3 01005 -482 318 0293 // ///// ///// //++ 7777 dballe-7.7/extra/crex/test-mare2.crex0000644000175000017500000000054712652630043014474 00000000000000CREX++ T000103 A001 D01036 B12015 B12014 D02024 B22001 B22011 B22021 B13031 B14015 B14031 B20063 B20063 B20063 B20063 B20033 B20031 B20032 B20034 B20037 B20038 B20036++ SHIP 270 012 1 2004 11 30 12 00 3390 02900 /// /// /// // //// /// // //// /// // //// /// // //// /// ///// //// //// //// //// //// // /// / // // /// //++ 7777 dballe-7.7/extra/crex/test-synop0.crex0000644000175000017500000000037412652630043014714 00000000000000CREX++ T000103 A000 D07005 B13023 B13013++ 10 837 1 2004 11 30 12 00 4822000 00992000 00550 09434 10094 -0017 07 080 0060 030 007 /// 0500 010 02 02 100 01 08 0045 35 61 60 01 08 06 0035 02 // // //// 03 // // //// // // // //// ///// /////++ 7777 dballe-7.7/libdballef.pc.in0000644000175000017500000000031512652630043012544 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libdballef Description: DB-All.e Fortran API Version: @VERSION@ Cflags: -I${includedir} Libs: -L${libdir} -ldballef dballe-7.7/run-local0000755000175000017500000000051312652630043011355 00000000000000#!/bin/bash TOP_SRCDIR=$(cd $(dirname $0) && pwd) export LD_LIBRARY_PATH="$TOP_SRCDIR/dballe:$LD_LIBRARY_PATH" export WREPORT_EXTRA_TABLES=$TOP_SRCDIR/tables export DBA_REPINFO=$TOP_SRCDIR/tables/repinfo.csv export DBA_TABLES=$TOP_SRCDIR/tables/ export PYTHONPATH=$TOP_SRCDIR/python export PATH="$TOP_SRCDIR/src:$PATH" exec "$@" dballe-7.7/run-check.conf.example0000644000175000017500000000020712652630043013713 00000000000000# Examples with odbc: #DBA_DB=odbc://testdsn #DBA_DB=odbc://user@testdsn #DBA_DB=odbc://user:pass@testdsn #DBA_DB=sqlite://test.sqlite dballe-7.7/libdballe.pc.in0000644000175000017500000000035612652630043012403 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libdballe Description: DB-All.e C library Version: @VERSION@ Requires: libwreport >= 1.0, sqlite3 Cflags: -I${includedir} Libs: -L${libdir} -ldballe dballe-7.7/run-check0000755000175000017500000000062712652630043011346 00000000000000#!/bin/sh TOP_SRCDIR=$(cd $(dirname $0) && pwd) export LD_LIBRARY_PATH="$TOP_SRCDIR/dballe:$LD_LIBRARY_PATH" export WREPORT_EXTRA_TABLES=$TOP_SRCDIR/tables for conffile in ./run-check.conf .git/run-check.conf do if [ -f "$conffile" ] then . "$conffile" export DBA_DB export DBA_DB_SQLITE export DBA_DB_POSTGRESQL export DBA_DB_MYSQL export DBA_DB_ODBC break fi done exec make check "$@" dballe-7.7/Makefile.am0000644000175000017500000000254412652630043011575 00000000000000## Process this file with automake to produce Makefile.in ACLOCAL_AMFLAGS = -I m4 SUBDIRS = tables dballe extra src if DO_DBALLEF SUBDIRS += fortran endif if DO_DOCS SUBDIRS += doc endif if DO_DBALLE_PYTHON SUBDIRS += python endif SUBDIRS += . #examples pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA=libdballe.pc libdballef.pc m4dir = $(datadir)/aclocal m4_DATA = libdballe.m4 libdballef.m4 man_MANS = dbatbl.1 dbamsg.1 dbadb.1 dbaexport.1 dbadb.1: src/dbadb doc/add_templates_to_manpage ( cd src && ./`basename $<` help manpage ) | ( cd $(srcdir) && $(srcdir)/doc/add_templates_to_manpage ) > $@ dbamsg.1: src/dbamsg doc/add_templates_to_manpage ( cd src && ./`basename $<` help manpage ) | ( cd $(srcdir) && $(srcdir)/doc/add_templates_to_manpage ) > $@ dbaexport.1: src/dbaexport COLUMNS=200 help2man --name='export data from DB-All.e' --section=1 --no-info --version-string="$(PACKAGE_VERSION)" $< > $@ %.1: src/% ( cd src && ./`basename $<` help manpage ) > $@ BUILT_SOURCES = dbaexport.1 EXTRA_DIST = LICENSE BENCHMARKS ODBC-TRACE-HOWTO autogen.sh \ libdballe.m4 libdballef.m4 \ libdballe.pc.in libdballef.pc.in \ $(conf_DATA) get_line_no run-check.conf.example \ run-check run-local run-bench show_code_notes \ UPGRADE-5.x \ dbaexport.1 \ fedora/SPECS/dballe.spec CLEANFILES = dbatbl.1 dbamsg.1 dbadb.1 dballe-7.7/configure.ac0000644000175000017500000002065212652630043012027 00000000000000dnl Process this file with autoconf to produce a configure script. AC_INIT(dballe, [7.7], [enrico@enricozini.org]) AC_CONFIG_SRCDIR([configure.ac]) AM_INIT_AUTOMAKE([foreign subdir-objects]) AC_CONFIG_HEADER(config.h) AC_CONFIG_MACRO_DIR([m4]) dnl Use libtool dnl AM_ENABLE_STATIC dnl AM_DISABLE_SHARED LT_INIT() LT_LANG([C++]) AM_PROG_LIBTOOL AC_ARG_ENABLE([dballef], [AS_HELP_STRING( [--enable-dballef], [build DB-All.e Fortran bindings])], [], [enable_dballef="yes"]) AC_ARG_ENABLE([dballe-python], [AS_HELP_STRING( [--enable-dballe-python], [build DB-All.e Python bindings])], [], [enable_dballe_python="yes"]) AC_ARG_ENABLE([docs], [AS_HELP_STRING( [--enable-docs], [enable building of the documentation])], [], [enable_docs="yes"]) AC_CHECK_PROG(have_latex2html, latex2html, yes, no) AC_CHECK_PROG(have_rst2html, rst2html, yes, no) dnl To use subdirs AC_PROG_MAKE_SET AC_LANG([C++]) AC_ISC_POSIX AC_PROG_CC AC_PROG_CXX AC_PROG_FC([gfortran pgf90 ifort g95 xlf90 f90]) F77=$FC dnl Use c++11 AX_CXX_COMPILE_STDCXX_11 AM_PROG_CC_STDC dnl Needed by subdir-objects AM_PROG_CC_C_O AC_SYS_LARGEFILE dnl See http://www.gossamer-threads.com/lists/xen/devel/275132 FILE_OFFSET_BITS_64= if test $ac_cv_sys_file_offset_bits = 64 then FILE_OFFSET_BITS_64=yes fi AM_CONDITIONAL([FILE_OFFSET_BITS_64], [test x"$FILE_OFFSET_BITS_64" = x"yes"]) dnl We want to invoke pkg-config directly PKG_PROG_PKG_CONFIG if test x$enable_docs = xyes then dnl Check for doxygen AC_CHECK_PROG(have_doxygen, doxygen, true) if test x$have_doxygen != xtrue then AC_MSG_WARN([doxygen was not found: documentation will not be built]) enable_docs=no fi fi dnl Check for gperf AC_CHECK_PROG(have_gperf, gperf, true) if test x$have_gperf != xtrue then AC_MSG_WARN([gperf was not found: relying on prebuilt sources]) has_build_gperf_sources=yes for f in dballe/core/record_keyword.cc dballe/core/aliases.cc dballe/msg/vars.cc do if ! test -f $f then has_build_gperf_sources=no AC_MSG_WARN([please extract $f from the distribution tarball]) fi done if test $has_build_gperf_sources = no then AC_MSG_ERROR([some gperf-generated source files are missing and gperf is not available to rebuild them]) fi fi dnl Check for missing functions in libc AC_CHECK_FUNC(vasprintf, , [ AC_DEFINE([USE_OWN_VASPRINTF], 1, [we need to use our own vasprintf]) ]) AC_CHECK_FUNC(bswap_32, , [ AC_DEFINE([USE_OWN_BSWAP], 1, [we need to use our own bswap_* functions]) ]) AC_CHECK_FUNC(strcasestr, [ AC_DEFINE([HAVE_STRCASESTR], 1, [we can use strcasestr]) ]) if test x$docdir = x then docdir='${datadir}/doc/${PACKAGE_TARNAME}' AC_SUBST(docdir) fi dnl Check for python AM_PATH_PYTHON([], [], [ enable_dballe_python=no ]) if test x$enable_dballe_python = xyes then PYTHON_CFLAGS=`unset CFLAGS; $PYTHON-config --cflags` AC_SUBST(PYTHON_CFLAGS) fi dnl Check for wreport PKG_CHECK_MODULES(WREPORT,libwreport >= 3.0) dnl Check for sqlite3 PKG_CHECK_MODULES(SQLITE3, sqlite3) dnl Check for libpq PKG_CHECK_EXISTS(libpq, [have_libpq=yes], [have_libpq=no]) if test x$have_libpq = xyes then PKG_CHECK_MODULES(LIBPQ, libpq) AC_DEFINE([HAVE_LIBPQ], 1, [PostgreSQL is available]) fi AM_CONDITIONAL([HAVE_LIBPQ], [test x"$have_libpq" = x"yes"]) dnl Check for libmysqlclient AC_PATH_PROG(mysql_config, [mysql_config]) if test x$mysql_config = x then have_mysql=no else have_mysql=yes MYSQL_CFLAGS=`$mysql_config --cflags` MYSQL_LIBS=`$mysql_config --libs_r` AC_SUBST(MYSQL_CFLAGS) AC_SUBST(MYSQL_LIBS) AC_DEFINE([HAVE_MYSQL], 1, [MySQL is available]) fi AM_CONDITIONAL([HAVE_MYSQL], [test x"$have_mysql" = x"yes"]) dnl Check for unixodbc have_odbc=yes AC_CHECK_HEADER(sql.h, AC_DEFINE(HAVE_ODBC_H, 1, sql.h (part of unixodbc) has been found), AC_MSG_WARN([*** sql.h not found. Check 'config.log' for more details.]) have_odbc=no ) AC_CHECK_LIB(odbc, SQLAllocHandle, LIBS="$LIBS -lodbc", AC_MSG_WARN([*** libodbc not found. Check 'config.log' for more details.]) have_odbc=no ) 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]) 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]) 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]) else dnl We don't always have the luxury of .pc files for lua, it seems have_lua=yes AC_CHECK_LIB([lua], [lua_gettop], [true], [have_lua=no]) AC_CHECK_HEADER([lua.h], [true], [have_lua=no]) if test x$have_lua = xyes then LUA_CFLAGS= LUA_LIBS="-llua" fi fi fi fi if test x$have_lua = xyes then AC_DEFINE([HAVE_LUA], 1, [lua is available]) fi AM_CONDITIONAL([LUA], [test x"$have_lua" = x"yes"]) dnl Check for popt AC_CHECK_HEADER(popt.h, AC_DEFINE(HAVE_POPT_H, 1, popt.h has been found), AC_MSG_ERROR([*** popt.h not found. Check 'config.log' for more details.]) ) AC_CHECK_LIB(popt, poptGetContext, LIBS="$LIBS -lpopt", AC_MSG_ERROR([*** libpopt not found. Check 'config.log' for more details.]) ) LIBS="$LIBS -lm" confdir='${sysconfdir}'"/$PACKAGE" AC_SUBST(confdir) # tabledir="`$PKG_CONFIG --variable=tabledir libwreport`" tabledir='${datadir}/wreport' AC_SUBST(tabledir) dnl def_tabledir=`echo "${sharedstatedir}/lib/$PACKAGE/tables"` dnl AC_DEFINE_UNQUOTED(TABLE_DIR, "$def_tabledir", "Default location for table files") dnl From libtool's documentation: dnl dnl This flag accepts an argument of the form `CURRENT[:REVISION[:AGE]]'. dnl dnl CURRENT dnl The most recent interface number that this library implements. dnl dnl REVISION dnl The implementation number of the CURRENT interface. dnl dnl AGE dnl The difference between the newest and oldest interfaces that this dnl library implements. In other words, the library implements all the dnl interface numbers in the range from number `CURRENT - AGE' to dnl `CURRENT'. dnl dnl If two libraries have identical CURRENT and AGE numbers, then the dnl dynamic linker chooses the library with the greater REVISION number. dnl dnl 3. If the library source code has changed at all since the last dnl update, then increment REVISION (`C:R:A' becomes `C:r+1:A'). dnl dnl 4. If any interfaces have been added, removed, or changed since the dnl last update, increment CURRENT, and set REVISION to 0. dnl dnl 5. If any interfaces have been added since the last public release, dnl then increment AGE. dnl dnl 6. If any interfaces have been removed since the last public release, dnl then set AGE to 0. LIBDBALLE_VERSION_INFO="7:3:0" LIBDBALLEF_VERSION_INFO="4:20:0" AC_SUBST(LIBDBALLE_VERSION_INFO) AC_SUBST(LIBDBALLEF_VERSION_INFO) dnl Enable extra compiler warnings AX_CXXFLAGS_WARN_ALL dnl warnings="-Wall -Wextra -Werror=return-type -Werror=empty-body" dnl CFLAGS="$warnings $CFLAGS" dnl CXXFLAGS="$warnings $CXXFLAGS" # Enforce dependencies if test x"$have_odbc" = x"yes"; then AC_DEFINE(HAVE_ODBC,[],[Have DB module]) fi if test x"$enable_dballef" = x"yes"; then AC_DEFINE(HAVE_DBALLEF,[],[Have Fortran bindings]) fi if test x"$enable_dballe_python" = x"yes"; then AC_DEFINE(HAVE_DBALLE_PYTHON,[],[Have Python bindings]) fi AM_CONDITIONAL([HAVE_ODBC], [test x"$have_odbc" = x"yes"]) AM_CONDITIONAL([DO_DBALLEF], [test x"$enable_dballef" = x"yes"]) AM_CONDITIONAL([DO_DBALLE_PYTHON], [test x"$enable_dballe_python" = x"yes"]) AM_CONDITIONAL([DO_DOCS], [test x"$enable_docs" = x"yes"]) AM_CONDITIONAL([HAVE_LATEX2HTML], [test x$have_latex2html = xyes]) AM_CONDITIONAL([HAVE_RST2HTML], [test x$have_rst2html = xyes]) AC_CONFIG_FILES([ Makefile dballe/Makefile fortran/Makefile src/Makefile tables/Makefile extra/Makefile python/Makefile doc/Makefile doc/libdballe.dox doc/libdballef.dox libdballe.pc libdballef.pc ]) AC_OUTPUT AC_MSG_NOTICE([ =================================================== $PACKAGE_NAME-$PACKAGE_VERSION configuration: AS_HELP_STRING([ODBC:], [$have_odbc]) AS_HELP_STRING([PostgreSQL:], [$have_libpq]) AS_HELP_STRING([MySQL:], [$have_mysql]) AS_HELP_STRING([Fortran:], [$enable_dballef]) AS_HELP_STRING([Python:], [$enable_dballe_python]) AS_HELP_STRING([documentation:], [$enable_docs]) AS_HELP_STRING([latex2html:], [$have_latex2html]) AS_HELP_STRING([rst2html:], [$have_rst2html]) ===================================================]) dballe-7.7/py-compile0000755000175000017500000001107612652630066011552 00000000000000#!/bin/sh # py-compile - Compile a Python program scriptversion=2011-06-08.12; # UTC # Copyright (C) 2000-2014 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . if [ -z "$PYTHON" ]; then PYTHON=python fi me=py-compile usage_error () { echo "$me: $*" >&2 echo "Try '$me --help' for more information." >&2 exit 1 } basedir= destdir= while test $# -ne 0; do case "$1" in --basedir) if test $# -lt 2; then usage_error "option '--basedir' requires an argument" else basedir=$2 fi shift ;; --destdir) if test $# -lt 2; then usage_error "option '--destdir' requires an argument" else destdir=$2 fi shift ;; -h|--help) cat <<\EOF Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..." Byte compile some python scripts FILES. Use --destdir to specify any leading directory path to the FILES that you don't want to include in the byte compiled file. Specify --basedir for any additional path information you do want to be shown in the byte compiled file. Example: py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py Report bugs to . EOF exit $? ;; -v|--version) echo "$me $scriptversion" exit $? ;; --) shift break ;; -*) usage_error "unrecognized option '$1'" ;; *) break ;; esac shift done files=$* if test -z "$files"; then usage_error "no files given" fi # if basedir was given, then it should be prepended to filenames before # byte compilation. if [ -z "$basedir" ]; then pathtrans="path = file" else pathtrans="path = os.path.join('$basedir', file)" fi # if destdir was given, then it needs to be prepended to the filename to # byte compile but not go into the compiled file. if [ -z "$destdir" ]; then filetrans="filepath = path" else filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)" fi $PYTHON -c " import sys, os, py_compile, imp files = '''$files''' sys.stdout.write('Byte-compiling python modules...\n') for file in files.split(): $pathtrans $filetrans if not os.path.exists(filepath) or not (len(filepath) >= 3 and filepath[-3:] == '.py'): continue sys.stdout.write(file) sys.stdout.flush() if hasattr(imp, 'get_tag'): py_compile.compile(filepath, imp.cache_from_source(filepath), path) else: py_compile.compile(filepath, filepath + 'c', path) sys.stdout.write('\n')" || exit $? # this will fail for python < 1.5, but that doesn't matter ... $PYTHON -O -c " import sys, os, py_compile, imp # pypy does not use .pyo optimization if hasattr(sys, 'pypy_translation_info'): sys.exit(0) files = '''$files''' sys.stdout.write('Byte-compiling python modules (optimized versions) ...\n') for file in files.split(): $pathtrans $filetrans if not os.path.exists(filepath) or not (len(filepath) >= 3 and filepath[-3:] == '.py'): continue sys.stdout.write(file) sys.stdout.flush() if hasattr(imp, 'get_tag'): py_compile.compile(filepath, imp.cache_from_source(filepath, False), path) else: py_compile.compile(filepath, filepath + 'o', path) sys.stdout.write('\n')" 2>/dev/null || : # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: dballe-7.7/run-bench0000755000175000017500000000232112652630043011341 00000000000000#!/usr/bin/env python3 import shutil import os import shlex import subprocess import sys env = dict(os.environ) def read_conffile(fd): for line in fd: line = line.strip() if not line or line.startswith("#"): continue if '=' in line: key, val = line.split("=", 1) val = shlex.split(val)[0] if val.startswith("$"): val = env[val[1:]] env[key] = val for conffile in ("./run-check.conf", ".git/run-check.conf"): if not os.path.exists(conffile): continue with open(conffile, "rt") as fd: read_conffile(fd) subprocess.check_call(["make", "-C", "dballe"]) subprocess.check_call(["make", "-C", "dballe", "bench-run"]) for arg in sys.argv[1:]: if '=' in arg: key, val = arg.split("=", 1) env[key] = val os.chdir("dballe") os.execve("../extra/runtest", ["../extra/runtest", "bench-run"], env) #if [ -d .svn ] #then # SVNID=$(svn info | sed -nre 's/^Revision: //p') #elif [ -d .git ] #then # SVNID=$(git svn info | sed -nre 's/^Revision: //p') #else # echo "No .svn or .git directory found" >&2 # exit 1 #fi # #cd src #eatmydata ../run-local ./benchmark > "bench/$SVNID-`hostname`-`date +%Y%m%d-%H%M%S`.csv" dballe-7.7/ODBC-TRACE-HOWTO0000644000175000017500000000033512652630043011721 00000000000000To trace the ODBC calls: mkdir /tmp/odbc cp /etc/odbcinst.ini /tmp/odbc cat << EOT >> /tmp/odbc/odbcinst.ini [ODBC] Trace = Yes TraceFile = /tmp/test.log EOT ODBCSYSINI=/tmp/odbc ./run-check ... dballe-7.7/TODO0000644000175000017500000000204712652630043010227 00000000000000DA TESTARE mail 2014-12-01 by dbranchini > $ dbadb wipe --dsn=sqlite:qualcosa.sqlite > segmentation fault (core dumped) aperto bug su sqliteodbc: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=771669 riscritta interfaccia bypassando odbc per sqlite (mail 2014-12-8 by ezini) __________________________________________________________________________ DA SISTEMARE mail 2014-11-12 by ppatruno > vengono importati due bufr da un file in memdb e poi exportati a un altro > file; la cosa viene fatta in due passi leggendo e scrivendo un bufr alla > volta. > La differenza tra i due trace è l'esecuzione di una dimenticami sul memdb > dopo l'importazione del primo bufr e così facendo il secondo bufr non viene > piu' letto dal file. Nel secondo trace la dimenticami non viene fatta e > tutto funziona leggendo anche il secondo bufr dal file. __________________________________________________________________________ DA IMPLEMENTARE riunione 2014-12-17 by ppatruno, ezini, dbranchini, edigiacomo > postgresql: bypassare odbc usando driver nativi dballe-7.7/config.sub0000755000175000017500000010646012652630066011533 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2015 Free Software Foundation, Inc. timestamp='2015-08-20' # 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 # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # 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;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2015 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." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # 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/'` 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* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os 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/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 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/'` ;; -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/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 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/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # 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 os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; 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 ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; 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) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) 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 ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; 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 ;; we32k) basic_machine=we32k-att ;; 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 ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # 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 ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -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. # The portable systems comes first. # 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]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -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* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -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 ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: dballe-7.7/UPGRADE-5.x0000644000175000017500000000713612652630043011165 00000000000000This is a summary of changes from DB-All.e 4.x that might require porting of Fortran code, or scripts using the command line tools, even if the Fortran API and the command line interfaces did not change. Changes in tables: * Tables are now in /usr/share/wreport * Table location can be customized with two environment variables: WREPORT_TABLES=(colon separated list of directories) The primary location(s) of tables. It has a compiled in default if it is not set. WREPORT_EXTRA_TABLES=(colon separated list of directories) Extra location(s) of tables. It is ignored if not set. The reason for having two variables is in their use: if you want to override the compiled in default, set WREPORT_TABLES. If you want to add tables to the compiled-in default, set WREPORT_EXTRA_TABLES. * Generic BUFR messages now use table B000000002001400.txt instead of B000000002001200.txt Local B table changes to follow the new WMO templates: * B12001 is replaced by B12101 * B12003 is replaced by B12103 * B10061 is replaced by B10060 * B10003 is replaced by B10008 Added to local B table: * B02003 TYPE OF MEASURING EQUIPMENT USED * B02004 TYPE OF INSTRUMENTATION FOR EVAPORATION MEASUREMENT OR TYPE OF C * B02013 SOLAR AND INFRARED RADIATION CORRECTION * B02014 TRACKING TECHNIQUE/STATUS OF SYSTEM USED * B04086 LONG TIME PERIOD OR DISPLACEMENT * B05015 LATITUDE DISPLACEMENT (HIGH ACCURACY) * B06015 LONGITUDE DISPLACEMENT (HIGH ACCURACY) * B07007 HEIGHT * B08002 VERTICAL SIGNIFICANCE (SURFACE OBSERVATIONS) * B08042 EXTENDED VERTICAL SOUNDING SIGNIFICANCE * B11043 MAXIMUM WIND GUST DIRECTION * B11061 ABSOLUTE WIND SHEAR IN 1 KM LAYER BELOW * B11062 ABSOLUTE WIND SHEAR IN 1 KM LAYER ABOVE * B12121 GROUND MINIMUM TEMPERATURE * B13033 EVAPORATION/EVAPOTRANSPIRATION * B14031 TOTAL SUNSHINE * B20017 CLOUD TOP DESCRIPTION Changes in levels and time ranges: * Meaningless level or timerange components now have a proper missing value instead of 0. The station level, for example, is now level 257,-,-,- and time range -,-,- * All cloud levels have been reorganised. For clouds levels, leveltype1 is always 256 and l1 is always missing. The cloud level is identified by leveltype2 and l2, as follows: Leveltype2 Description 258 Cloud Data group, L2 = 1 low clouds, 2 middle clouds, 3 high clouds, 0 others 259 Individual cloud groups, L2 = group number 260 Cloud drift, L2 = group number 261 Cloud elevation, L2 = group number 262 Direction and elevation of clouds, L2 is ignored Command line tools changes: * dbamsg dump does not show attributes trailing at the end of the message dump, but it only shows them attached to their variables. * dbamsg dump now also shows data present bitmaps as a Cxxyyy variable with a string value of '-' when the bitmap has 'missing' and '+' when the bitmap has a value. Miscellaneous changes: * bound checking of variable values now uses the most restrictive range between BUFR and CREX (it used to use the least restrictive) * The minimal MySQL versione should be 5.1, or one that supports subqueries, to adapt to newer MySQLs dropping the old custom semanthics of GROUP BY … HAVING … * vertical significance of synop clouds is now imported as a measured value * importing messages with a sensor, barometer or anemometer height indicators will now by default import the values in the appropriate vertical level. An option will be soon provided for 'simplified' imports, whereby data are imported in standard levels with the correct height added as an attribute. dballe-7.7/fortran/0000755000175000017500000000000012653425053011273 500000000000000dballe-7.7/fortran/check_fdballe.f900000644000175000017500000001661412652630043014265 00000000000000 program check_fdballe ! ***************************************** ! * Test suite for DBALLE Fortran bindings ! ***************************************** use dbtest include "dballef.h" integer :: dbahandle, handle,i,i1,i2,i3,i4,i5,i6,ival,saved_id real :: rval double precision :: dval character (len=10) :: param character (len=255) :: cval external :: testcb ! call fdba_error_set_callback(0, testcb, 2, i) ! Database login call dbinit(dbahandle) ! Open a session call idba_preparati(dbahandle, handle, "write", "write", "write") call ensure_no_error("preparati") ! Clear the database call idba_scopa(handle, "") call ensure_no_error("scopa") ! Insert some data call idba_setd(handle, "lat", 30D00) call ensure_no_error("setd 0") call idba_setr(handle, "lon", 10.0) call ensure_no_error("setr 1") call idba_setc(handle, "mobile", "0") call ensure_no_error("setc 2") ! { "year_ident", "2003" }, ! { "month_ident", "3" }, ! { "day_ident", "23" }, ! { "hour_ident", "12" }, ! { "min_ident", "30" }, ! { "height", "42" }, ! { "heightbaro", "234" }, ! { "block", "1" }, ! { "station", "52" }, ! { "name", "Cippo Lippo" }, call idba_seti(handle, "year", 2006) call ensure_no_error("seti 3") call idba_seti(handle, "month", 1) call ensure_no_error("seti 4") call idba_seti(handle, "day", 2) call ensure_no_error("seti 5") call idba_seti(handle, "hour", 3) call ensure_no_error("seti 6") call idba_seti(handle, "min", 4) call ensure_no_error("seti 7") call idba_setc(handle, "leveltype1", "1") call ensure_no_error("setc 8") call idba_seti(handle, "l1", 1) call ensure_no_error("seti 9") call idba_setc(handle, "leveltype2", "1") call ensure_no_error("seti 10") call idba_seti(handle, "l2", 1) call ensure_no_error("seti 11") call idba_seti(handle, "pindicator", 20) call ensure_no_error("seti 12") call idba_seti(handle, "p1", 1) call ensure_no_error("seti 13") call idba_seti(handle, "p2", 1) call ensure_no_error("seti 14") call idba_setc(handle, "rep_memo", "synop") call ensure_no_error("seti 15") call idba_setc(handle, "B01011", "DB-All.e!") call ensure_no_error("setc 16") ! Perform the insert call idba_prendilo(handle) call ensure_no_error("first prendilo") ! Try to read the id of the pseudoana data just inserted call idba_enqi(handle, "ana_id", i) call ensure_no_error("enqi ana_id") ! Try to read the context id of the data just inserted call idba_enqi(handle, "context_id", i) call ensure_no_error("enqi context_id") ! Insert some QC flags call idba_setc(handle, "*B33002", "1") call ensure_no_error("critica setc 0") call idba_setc(handle, "*B33003", "1") call ensure_no_error("critica setc 1") call idba_setc(handle, "*var", "B01011") call idba_critica(handle) ! call idba_critica(handle, "B01011") call ensure_no_error("prima critica") ! Query back the data ! call idba_ricominciamo(handle) call idba_unsetall(handle) call ensure_no_error("ricominciamo") call idba_setr(handle, "latmin", 20.0) call ensure_no_error("query setf 0") call idba_setr(handle, "latmax", 50.0) call ensure_no_error("query setf 1") call idba_setr(handle, "lonmin", 5.0) call ensure_no_error("query setf 2") call idba_setr(handle, "lonmax", 20.0) call ensure_no_error("query setf 3") call idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto") call ensure("voglioquesto result", i.eq.1) ! Read the results of the query ! TODO: make a for loop instead do while (i.gt.0) call idba_dammelo(handle, param) call ensure_no_error("dammelo") call idba_enqc(handle, param, cval) call ensure_no_error("dammelo enqc 0") call idba_enqi(handle, "year", ival) call ensure_no_error("dammelo enqi 1") call idba_enqr(handle, "lat", rval) call ensure_no_error("dammelo enqr 2") call idba_enqd(handle, "lon", dval) call ensure_no_error("dammelo enqd 3") call idba_enqc(handle, "lon", cval) call ensure_no_error("dammelo enqc 4") call idba_enqdate(handle, i1, i2, i3, i4, i5, i6) call ensure_no_error("dammelo enqdate") call ensure("enqdate i1", i1.eq.2006) call ensure("enqdate i2", i2.eq.1) call ensure("enqdate i3", i3.eq.2) call ensure("enqdate i4", i4.eq.3) call ensure("enqdate i5", i5.eq.4) call ensure("enqdate i6", i6.eq.0) call idba_enqlevel(handle, i1, i2, i3, i4) call ensure_no_error("dammelo enqlevel") call ensure("enqlevel i1", i1.eq.1) call ensure("enqlevel i2", i2.eq.1) call ensure("enqlevel i3", i3.eq.1) call ensure("enqlevel i4", i4.eq.1) call idba_enqtimerange(handle, i1, i2, i3) call ensure_no_error("dammelo enqtimerange") call ensure("enqdate i1", i1.eq.20) call ensure("enqdate i2", i2.eq.1) call ensure("enqdate i3", i3.eq.1) call idba_enqi(handle, "ana_id", ival) call ensure_no_error("dammelo enqi ana_id") call ensure("ana_id", ival.eq.1) call idba_enqi(handle, "context_id", ival) call ensure_no_error("dammelo enqi context_id") ! Save the id for reusing it later saved_id = ival call idba_voglioancora(handle, i1) call ensure_no_error("voglioancora") do while (i1.gt.0) call idba_ancora(handle, param) call ensure_no_error("ancora") call idba_enqc(handle, param, cval) call ensure_no_error("ancora enqc") i1 = i1 - 1 enddo ! Perform some useless scusa just to test the parser call idba_setc(handle, "*varlist", "*B12345"); call ensure_no_error("scusa setc 1") call idba_scusa(handle); call ensure_no_error("scusa 1") call idba_setc(handle, "*varlist", "*B12345,*B54321"); call ensure_no_error("scusa setc 2") call idba_scusa(handle); call ensure_no_error("scusa 2") i = i - 1 enddo ! Remove the QC data for saved_data call idba_seti(handle, "*context_id", saved_id); call ensure_no_error("scusa seti 3") call idba_setc(handle, "*var", "*B01011") call ensure_no_error("scusa setc 3") call idba_scusa(handle); call ensure_no_error("scusa 3") call idba_unsetall(handle) call ensure_no_error("unsetall quantesono 1") call idba_quantesono(handle, i) call ensure_no_error("quantesono 1") call ensure("quantesono 1", i.eq.1) call idba_setd(handle, "latmax", 20D00) call ensure_no_error("seti quantesono 2") call idba_quantesono(handle, i) call ensure_no_error("quantesono 2") call ensure("quantesono 1", i.eq.0) call idba_fatto(handle) call ensure_no_error("fatto") call idba_arrivederci(dbahandle) call ensure_no_error("arrivederci") ! If we made it so far, exit with no error print*,"check_fdballe: all tests succeed." call exit (0) end program include "check-utils.h" dballe-7.7/fortran/mkmsg.f900000644000175000017500000000614512652630043012653 00000000000000 program mkmsg ! **************************** ! * Create a test message file ! **************************** integer handle, nstaz, ndata, nattr integer i, i1, i2, tmp integer id,height,codrete character fname*256,encoding*10,cname*20,rete*20,value*255 character btable*10,starbtable*10 real*8 dlat,dlon external errorrep call idba_error_set_callback(0, errorrep, 2, i) ! Open a session call getarg(1,fname) call getarg(2,encoding) call idba_messaggi(handle, fname, "w", encoding) call idba_setd(handle, "lat", 44.D0) call idba_setd(handle, "lon", 11.D0) call idba_setlevel(handle, 102, 2000, 0, 0) call idba_settimerange(handle, 254, 0, 0) call idba_setdate(handle, 2008, 7, 6, 5, 4, 3) ! One without setting 'query' call idba_seti(handle, "B12001", 2731+120) call idba_prendilo(handle) call idba_seti(handle, "*B33192", 74) call idba_seti(handle, "*B33193", 81) call idba_seti(handle, "*B33194", 59) call idba_critica(handle) call idba_seti(handle, "B12003", 2731+100) call idba_prendilo(handle) ! One setting 'query' to subset call idba_setc(handle, "query", "subset") call idba_seti(handle, "B12001", 2731+110) call idba_prendilo(handle) call idba_seti(handle, "*B33192", 47) call idba_seti(handle, "*B33193", 18) call idba_seti(handle, "*B33194", 95) call idba_critica(handle) call idba_seti(handle, "B12003", 2731+100) call idba_prendilo(handle) ! One setting 'query' to message, and making a synop call idba_setc(handle, "query", "message") call idba_setc(handle, "rep_memo", "synop") call idba_seti(handle, "B12001", 2731+90) call idba_prendilo(handle) call idba_seti(handle, "*B33007", 81) call idba_critica(handle) call idba_seti(handle, "B12003", 2731+80) call idba_seti(handle, "B13003", 80) call idba_prendilo(handle) ! One setting 'query' to message, and making a synop call idba_setc(handle, "query", "message synop") call idba_setc(handle, "rep_memo", "synop") call idba_seti(handle, "B12001", 2731+90) call idba_prendilo(handle) call idba_fatto(handle) call exit (0) end ! ******************** ! * Utility functions ! ******************** ! Compute the length of a string integer function istrlen(string) character string*(*) istrlen = len(string) do while ((string(istrlen:istrlen).eq." " .or. & string(istrlen:istrlen).eq."").and. & istrlen.gt.0) istrlen = istrlen - 1 enddo return end subroutine errorrep(val) integer val character buf*1000 ier = idba_error_code() if (ier.ne.0) then print *,ier," error in ",val call idba_error_message(buf) print *,buf(:istrlen(buf)) call idba_error_context(buf) print *,buf(:istrlen(buf)) call idba_error_details(buf) print *,buf(:istrlen(buf)) call exit (1) end if return end dballe-7.7/fortran/fortran.dox0000644000175000017500000000071712652630043013403 00000000000000/** @defgroup fortran Dballe fortran bindings Fortran bindings of Dballe. The bindings offer two different interfaces: a simplified interface and a full interface. The simplified interface allows for writing code quickly, while the full interface exports every part of Dballe, making it possible to write more complex programs, such as programs that run run more queries at the same time, or that perform queries while getting the results of other queries. */ dballe-7.7/fortran/dballeff.h0000644000175000017500000002443312652630043013125 00000000000000 ! ! Interface file for DB-ALLe ! ! Copyright (C) 2005,2006 ARPA-SIM ! ! This program is free software; you can redistribute it and/or modify ! it under the terms of the GNU General Public License as published by ! the Free Software Foundation; either version 2 of the License. ! ! This program is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! GNU General Public License for more details. ! ! You should have received a copy of the GNU General Public License ! along with this program; if not, write to the Free Software ! Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ! ! Author: Enrico Zini ! ! missing value INTEGER, PARAMETER :: & dba_int_b = SELECTED_INT_KIND(1), & ! Byte integer dba_int_s = SELECTED_INT_KIND(4), & ! Short integer dba_int_l = SELECTED_INT_KIND(8) ! Long integer INTEGER, PARAMETER :: & dba_fp_s = SELECTED_REAL_KIND(6), & ! Single precision dba_fp_d = SELECTED_REAL_KIND(15) ! Double precision REAL, PARAMETER :: DBA_MVR = HUGE(1.0) !REAL(dba_kind=dba_fp_s), PARAMETER :: = HUGE(1.0_dba_fp_s) REAL(kind=dba_fp_d), PARAMETER :: DBA_MVD = HUGE(1.0_dba_fp_d) !REAL(kind=dba_fp_d), PARAMETER :: DBA_MVD = 1.79769D308 INTEGER, PARAMETER :: DBA_MVI = HUGE(0) INTEGER(kind=dba_int_b), PARAMETER :: DBA_MVB = HUGE(0_dba_int_b) CHARACTER(len=1), PARAMETER :: DBA_MVC = char(0) ! Get/Set routines interface idba_enq integer function idba_enqb(handle,param,value) integer, intent(in) :: handle integer (kind=1),intent(out) :: value character (len=*), intent(in) :: param end function idba_enqb integer function idba_enqi(handle,param,value) integer, intent(in) :: handle integer, intent(out) :: value character (len=*), intent(in) :: param end function idba_enqi integer function idba_enqr(handle,param,value) integer, intent(in) :: handle real, intent(out) :: value character (len=*), intent(in) :: param end function idba_enqr integer function idba_enqd(handle,param,value) integer, intent(in) :: handle double precision, intent(out) :: value character (len=*), intent(in) :: param end function idba_enqd integer function idba_enqc(handle,param,value) integer, intent(in) :: handle character (len=*), intent(in) :: param character (len=*), intent(out) :: value end function idba_enqc end interface interface idba_set integer function idba_setb(handle,param,value) integer, intent(in) :: handle integer (kind=1), intent(in) :: value character (len=*), intent(in) :: param end function idba_setb integer function idba_seti(handle,param,value) integer, intent(in) :: handle,value character (len=*), intent(in) :: param end function idba_seti integer function idba_setr(handle,param,value) integer, intent(in) :: handle real, intent(in) :: value character (len=*), intent(in) :: param end function idba_setr integer function idba_setd(handle,param,value) integer, intent(in) :: handle double precision, intent(in) :: value character (len=*), intent(in) :: param end function idba_setd integer function idba_setc(handle,param,value) integer, intent(in) :: handle character (len=*), intent(in) :: param,value end function idba_setc end interface interface ! Error handling routines subroutine idba_error_message(message) character (len=*), intent(out) :: message end subroutine idba_error_message subroutine idba_error_context(message) character (len=*), intent(out) :: message end subroutine idba_error_context subroutine idba_error_details(message) character (len=*), intent(out) :: message end subroutine idba_error_details integer function idba_error_code() end function idba_error_code integer function idba_error_set_callback(code,func,data,handle) integer, intent(in) :: code external :: func integer, intent(in) :: data integer, intent(out) :: handle end function idba_error_set_callback integer function idba_error_remove_callback(handle) integer, intent(in) :: handle end function idba_error_remove_callback integer function idba_default_error_handler(debug) logical, intent(in) :: debug end function idba_default_error_handler integer function idba_error_handler_tolerating_overflows(debug) logical, intent(in) :: debug end function idba_error_handler_tolerating_overflows ! Init/Shutdown routines integer function idba_presentati(dbahandle, dsn, user, password) integer, intent(out) :: dbahandle character (len=*), intent(in) :: dsn,user,password end function idba_presentati integer function idba_arrivederci(dbahandle) integer, intent(in) :: dbahandle end function idba_arrivederci integer function idba_preparati(dbahandle, handle, anaflag, dataflag, attrflag) integer, intent(in) :: dbahandle integer, intent(out) :: handle character (len=*), intent(in) :: anaflag,dataflag,attrflag end function idba_preparati integer function idba_messaggi(handle, filename, mode, type) integer, intent(out) :: handle character (len=*), intent(in) :: filename,mode,type end function idba_messaggi integer function idba_messages_open_input(handle, filename, mode, format, simplified) integer, intent(in) :: handle character (len=*), intent(in) :: filename,mode,format logical, intent(in) :: simplified end function idba_messages_open_input integer function idba_messages_open_output(handle, filename, mode, format) integer, intent(in) :: handle character (len=*), intent(in) :: filename,mode,format end function idba_messages_open_output integer function idba_messages_read_next(handle, status) integer, intent(in) :: handle logical, intent(out) :: status end function idba_messages_read_next integer function idba_messages_write_next(handle, template_name) integer, intent(in) :: handle character (len=*), intent(in) :: template_name end function idba_messages_write_next integer function idba_fatto(handle) integer, intent(in) :: handle end function idba_fatto integer function idba_unset(handle,param) integer, intent(in) :: handle character (len=*), intent(in) :: param end function idba_unset integer function idba_unsetall(handle) integer, intent(in) :: handle end function idba_unsetall integer function idba_remove_all(handle) integer, intent(in) :: handle end function idba_remove_all integer function idba_unsetb(handle) integer, intent(in) :: handle end function idba_unsetb integer function idba_setcontextana(handle) integer, intent(in) :: handle end function idba_setcontextana integer function idba_enqlevel(handle,ltype1,l1,ltype2,l2) integer, intent(in) :: handle integer, intent(out) :: ltype1,l1,ltype2,l2 end function idba_enqlevel integer function idba_setlevel(handle,ltype1,l1,ltype2,l2) integer, intent(in) :: handle,ltype1,l1,ltype2,l2 end function idba_setlevel integer function idba_enqtimerange(handle,ptype,p1,p2) integer, intent(in) :: handle integer, intent(out) :: ptype,p1,p2 end function idba_enqtimerange integer function idba_settimerange(handle,ptype,p1,p2) integer, intent(in) :: handle,ptype,p1,p2 end function idba_settimerange integer function idba_enqdate(handle,year,month,day,hour,min,sec) integer, intent(in) :: handle integer, intent(out) :: year,month,day,hour,min,sec end function idba_enqdate integer function idba_setdate(handle,year,month,day,hour,min,sec) integer, intent(in) :: handle,year,month,day,hour,min,sec end function idba_setdate integer function idba_setdatemin(handle,year,month,day,hour,min,sec) integer, intent(in) :: handle,year,month,day,hour,min,sec end function idba_setdatemin integer function idba_setdatemax(handle,year,month,day,hour,min,sec) integer, intent(in) :: handle,year,month,day,hour,min,sec end function idba_setdatemax ! Action routines integer function idba_scopa(handle, repinfofile) integer, intent(in) :: handle character (len=*), intent(in) :: repinfofile end function idba_scopa integer function idba_quantesono(handle, count) integer, intent(in) :: handle integer, intent(out) :: count end function idba_quantesono integer function idba_elencamele(handle) integer, intent(in) :: handle end function idba_elencamele integer function idba_voglioquesto(handle, count) integer, intent(in) :: handle integer, intent(out) :: count end function idba_voglioquesto integer function idba_dammelo(handle,param) integer, intent(in) :: handle character (len=*), intent(out) :: param end function idba_dammelo integer function idba_prendilo(handle) integer, intent(in) :: handle end function idba_prendilo integer function idba_dimenticami(handle) integer, intent(in) :: handle end function idba_dimenticami integer function idba_voglioancora(handle, count) integer, intent(in) :: handle integer, intent(out) :: count end function idba_voglioancora integer function idba_ancora(handle,param) integer, intent(in) :: handle character (len=*), intent(out) :: param end function idba_ancora integer function idba_critica(handle) integer, intent(in) :: handle end function idba_critica integer function idba_scusa(handle) integer, intent(in) :: handle end function idba_scusa ! Pretty printing routines integer function idba_spiegal(handle,ltype1,l1,ltype2,l2,result) integer, intent(in) :: handle,ltype1,l1,ltype2,l2 character (len=*), intent(out) :: result end function idba_spiegal integer function idba_spiegat(handle,ptype,p1,p2,result) integer, intent(in) :: handle,ptype,p1,p2 character (len=*), intent(out) :: result end function idba_spiegat integer function idba_spiegab(handle,varcode,var,result) integer, intent(in) :: handle character (len=*), intent(in) :: varcode,var character (len=*), intent(out) :: result end function idba_spiegab end interface dballe-7.7/fortran/handles.h0000644000175000017500000000641512652630043013004 00000000000000/* * Copyright (C) 2005--2010 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef FDBA_HANDLES_H #define FDBA_HANDLES_H #include #include namespace dballe { struct DB; namespace fortran { struct API; #if 0 #define FDBA_HANDLE_END_DECL(name) }; \ extern struct fdba_handle_##name _##name[]; \ void fdba_handle_init_##name(); \ dba_err fdba_handle_alloc_##name(int* res); \ void fdba_handle_release_##name(int hnd); #define FDBA_HANDLE_BODY(name, size, desc) \ struct fdba_handle_##name _##name[size]; \ static int _##name##_last = 0; \ /* Initialize the handle storage */ \ void fdba_handle_init_##name() { \ int i; \ for (i = 0; i < size; i++) \ _##name[i].used = 0; \ } \ /* Allocate a new handle */ \ dba_err fdba_handle_alloc_##name(int* res) { \ if (_##name##_last < size) { \ *res = _##name##_last++; \ } else { \ int i, found = 0; \ for (i = 0; i < size && !found; i++) \ if (_##name[i].used == 0) { \ *res = i; \ found = 1; \ } \ if (!found) \ return dba_error_handles("No more handles for " desc ". The maximum limit is %d: to increase it, recompile dballe setting " #size " to a higher value", size); \ } \ /* Setup the new handle */ \ _##name[*res].used = 1; \ return dba_error_ok(); \ } \ /* Release a handle */ \ void fdba_handle_release_##name(int hnd) { \ assert(hnd < size); \ assert(_##name[hnd].used == 1); \ _##name[hnd].used = 0; \ if (hnd == _##name##_last - 1) \ _##name##_last--; \ } #define FDBA_HANDLE(name, hnd) (_##name[hnd]) #endif struct HBase { bool used; HBase() : used(false) {} void start() { used = true; } void stop() { used = false; } }; template struct Handler { T* records; int next; const char* name; const char* def; size_t in_use; void init(const char* name, const char* def) { this->name = name; this->def = def; records = new T[MAX]; next = 0; in_use = 0; } T& get(int id) { assert(records[id].used); return records[id]; } int request() { for (int i = 0; i < MAX && (records[next].used); ++i) next = (next + 1) % MAX; if (records[next].used) wreport::error_handles::throwf("No more handles for %s. The maximum limit is %d: to increase it, recompile DB-All.e setting %s to a higher value", name, MAX, def); /* Setup the new handle */ records[next].start(); ++in_use; return next; } void release(int h) { assert(in_use); assert(records[h].used); if (records[h].used) { records[h].stop(); --in_use; } } }; /// Initialise error handlers void error_init(); } } #endif dballe-7.7/fortran/check_spiegab.f900000644000175000017500000000052712652630043014302 00000000000000program test integer :: handle integer :: error_handle character(len=255) :: prettyvalue include "dballef.h" call idba_error_set_callback(0, idba_default_error_handler, 42, error_handle) call idba_messaggi(handle,"/dev/null", "w", "BUFR") call idba_spiegab(handle, "B12101", "1234", prettyvalue) call idba_fatto(handle) end program test dballe-7.7/fortran/Makefile.in0000644000175000017500000016540512653425052013272 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @DO_DBALLEF_TRUE@@FILE_OFFSET_BITS_64_TRUE@am__append_1 = -D_FILE_OFFSET_BITS=64 @DO_DBALLEF_TRUE@check_PROGRAMS = check_missing_msg$(EXEEXT) \ @DO_DBALLEF_TRUE@ check_real0$(EXEEXT) check_range$(EXEEXT) \ @DO_DBALLEF_TRUE@ check_fdballe$(EXEEXT) check_attrs$(EXEEXT) \ @DO_DBALLEF_TRUE@ check_missing$(EXEEXT) \ @DO_DBALLEF_TRUE@ check_segfault1$(EXEEXT) \ @DO_DBALLEF_TRUE@ check_multiplehandler$(EXEEXT) \ @DO_DBALLEF_TRUE@ check_spiegab$(EXEEXT) \ @DO_DBALLEF_TRUE@ check_messages$(EXEEXT) @DO_DBALLEF_TRUE@am__append_2 = -O0 @DO_DBALLEF_TRUE@noinst_PROGRAMS = dumpmsg_dballe$(EXEEXT) \ @DO_DBALLEF_TRUE@ mkmsg$(EXEEXT) mkmsg-sca$(EXEEXT) \ @DO_DBALLEF_TRUE@ genattr$(EXEEXT) dump_dballe$(EXEEXT) \ @DO_DBALLEF_TRUE@ check_messages_stdinstdout$(EXEEXT) subdir = fortran ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/m4_ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am \ $(am__dist_dballeinclude_HEADERS_DIST) \ $(am__dist_noinst_HEADERS_DIST) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" \ "$(DESTDIR)$(dballeincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) @DO_DBALLEF_TRUE@libdballef_la_DEPENDENCIES = ../dballe/libdballe.la am__libdballef_la_SOURCES_DIST = error.cc trace.cc binding.cc @DO_DBALLEF_TRUE@am_libdballef_la_OBJECTS = error.lo trace.lo \ @DO_DBALLEF_TRUE@ binding.lo libdballef_la_OBJECTS = $(am_libdballef_la_OBJECTS) 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 = libdballef_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(AM_CXXFLAGS) $(CXXFLAGS) $(libdballef_la_LDFLAGS) $(LDFLAGS) \ -o $@ @DO_DBALLEF_TRUE@am_libdballef_la_rpath = -rpath $(libdir) PROGRAMS = $(noinst_PROGRAMS) am__check_attrs_SOURCES_DIST = test.f90 dbtest.f90 check_attrs.f90 @DO_DBALLEF_TRUE@am__objects_1 = check_attrs-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_attrs-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_attrs_OBJECTS = $(am__objects_1) \ @DO_DBALLEF_TRUE@ check_attrs-check_attrs.$(OBJEXT) check_attrs_OBJECTS = $(am_check_attrs_OBJECTS) @DO_DBALLEF_TRUE@check_attrs_DEPENDENCIES = ./libdballef.la check_attrs_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(check_attrs_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__check_fdballe_SOURCES_DIST = test.f90 dbtest.f90 check_fdballe.f90 @DO_DBALLEF_TRUE@am__objects_2 = check_fdballe-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_fdballe-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_fdballe_OBJECTS = $(am__objects_2) \ @DO_DBALLEF_TRUE@ check_fdballe-check_fdballe.$(OBJEXT) check_fdballe_OBJECTS = $(am_check_fdballe_OBJECTS) @DO_DBALLEF_TRUE@check_fdballe_DEPENDENCIES = ./libdballef.la check_fdballe_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(check_fdballe_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__check_messages_SOURCES_DIST = test.f90 dbtest.f90 \ check_messages.f90 @DO_DBALLEF_TRUE@am__objects_3 = check_messages-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_messages-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_messages_OBJECTS = $(am__objects_3) \ @DO_DBALLEF_TRUE@ check_messages-check_messages.$(OBJEXT) check_messages_OBJECTS = $(am_check_messages_OBJECTS) @DO_DBALLEF_TRUE@check_messages_DEPENDENCIES = ./libdballef.la check_messages_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(FCLD) \ $(check_messages_FCFLAGS) $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ am__check_messages_stdinstdout_SOURCES_DIST = test.f90 dbtest.f90 \ check_messages_stdinstdout.f90 @DO_DBALLEF_TRUE@am__objects_4 = \ @DO_DBALLEF_TRUE@ check_messages_stdinstdout-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_messages_stdinstdout-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_messages_stdinstdout_OBJECTS = \ @DO_DBALLEF_TRUE@ $(am__objects_4) \ @DO_DBALLEF_TRUE@ check_messages_stdinstdout-check_messages_stdinstdout.$(OBJEXT) check_messages_stdinstdout_OBJECTS = \ $(am_check_messages_stdinstdout_OBJECTS) @DO_DBALLEF_TRUE@check_messages_stdinstdout_DEPENDENCIES = \ @DO_DBALLEF_TRUE@ ./libdballef.la check_messages_stdinstdout_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(FCLD) \ $(check_messages_stdinstdout_FCFLAGS) $(FCFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am__check_missing_SOURCES_DIST = test.f90 dbtest.f90 check_missing.f90 @DO_DBALLEF_TRUE@am__objects_5 = check_missing-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_missing-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_missing_OBJECTS = $(am__objects_5) \ @DO_DBALLEF_TRUE@ check_missing-check_missing.$(OBJEXT) check_missing_OBJECTS = $(am_check_missing_OBJECTS) @DO_DBALLEF_TRUE@check_missing_DEPENDENCIES = ./libdballef.la check_missing_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(check_missing_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__check_missing_msg_SOURCES_DIST = test.f90 check_missing_msg.f90 @DO_DBALLEF_TRUE@am_check_missing_msg_OBJECTS = \ @DO_DBALLEF_TRUE@ check_missing_msg-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_missing_msg-check_missing_msg.$(OBJEXT) check_missing_msg_OBJECTS = $(am_check_missing_msg_OBJECTS) @DO_DBALLEF_TRUE@check_missing_msg_DEPENDENCIES = ./libdballef.la check_missing_msg_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(FCLD) \ $(check_missing_msg_FCFLAGS) $(FCFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am__check_multiplehandler_SOURCES_DIST = test.f90 dbtest.f90 \ check_multiplehandler.f90 @DO_DBALLEF_TRUE@am__objects_6 = check_multiplehandler-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_multiplehandler-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_multiplehandler_OBJECTS = $(am__objects_6) \ @DO_DBALLEF_TRUE@ check_multiplehandler-check_multiplehandler.$(OBJEXT) check_multiplehandler_OBJECTS = $(am_check_multiplehandler_OBJECTS) @DO_DBALLEF_TRUE@check_multiplehandler_DEPENDENCIES = ./libdballef.la check_multiplehandler_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(FCLD) \ $(check_multiplehandler_FCFLAGS) $(FCFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am__check_range_SOURCES_DIST = test.f90 dbtest.f90 check_range.f90 @DO_DBALLEF_TRUE@am__objects_7 = check_range-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_range-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_range_OBJECTS = $(am__objects_7) \ @DO_DBALLEF_TRUE@ check_range-check_range.$(OBJEXT) check_range_OBJECTS = $(am_check_range_OBJECTS) @DO_DBALLEF_TRUE@check_range_DEPENDENCIES = ./libdballef.la check_range_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(check_range_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__check_real0_SOURCES_DIST = test.f90 dbtest.f90 check_real0.f90 @DO_DBALLEF_TRUE@am__objects_8 = check_real0-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_real0-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_real0_OBJECTS = $(am__objects_8) \ @DO_DBALLEF_TRUE@ check_real0-check_real0.$(OBJEXT) check_real0_OBJECTS = $(am_check_real0_OBJECTS) @DO_DBALLEF_TRUE@check_real0_DEPENDENCIES = ./libdballef.la check_real0_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(check_real0_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__check_segfault1_SOURCES_DIST = test.f90 dbtest.f90 \ check_segfault1.f90 @DO_DBALLEF_TRUE@am__objects_9 = check_segfault1-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_segfault1-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_segfault1_OBJECTS = $(am__objects_9) \ @DO_DBALLEF_TRUE@ check_segfault1-check_segfault1.$(OBJEXT) check_segfault1_OBJECTS = $(am_check_segfault1_OBJECTS) @DO_DBALLEF_TRUE@check_segfault1_DEPENDENCIES = ./libdballef.la check_segfault1_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(FCLD) \ $(check_segfault1_FCFLAGS) $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ am__check_spiegab_SOURCES_DIST = test.f90 dbtest.f90 check_spiegab.f90 @DO_DBALLEF_TRUE@am__objects_10 = check_spiegab-test.$(OBJEXT) \ @DO_DBALLEF_TRUE@ check_spiegab-dbtest.$(OBJEXT) @DO_DBALLEF_TRUE@am_check_spiegab_OBJECTS = $(am__objects_10) \ @DO_DBALLEF_TRUE@ check_spiegab-check_spiegab.$(OBJEXT) check_spiegab_OBJECTS = $(am_check_spiegab_OBJECTS) @DO_DBALLEF_TRUE@check_spiegab_DEPENDENCIES = ./libdballef.la check_spiegab_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(check_spiegab_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__dump_dballe_SOURCES_DIST = dump_dballe.f90 @DO_DBALLEF_TRUE@am_dump_dballe_OBJECTS = \ @DO_DBALLEF_TRUE@ dump_dballe-dump_dballe.$(OBJEXT) dump_dballe_OBJECTS = $(am_dump_dballe_OBJECTS) @DO_DBALLEF_TRUE@dump_dballe_DEPENDENCIES = ../fortran/libdballef.la dump_dballe_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(dump_dballe_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__dumpmsg_dballe_SOURCES_DIST = dumpmsg_dballe.f90 @DO_DBALLEF_TRUE@am_dumpmsg_dballe_OBJECTS = \ @DO_DBALLEF_TRUE@ dumpmsg_dballe-dumpmsg_dballe.$(OBJEXT) dumpmsg_dballe_OBJECTS = $(am_dumpmsg_dballe_OBJECTS) @DO_DBALLEF_TRUE@dumpmsg_dballe_DEPENDENCIES = \ @DO_DBALLEF_TRUE@ ../fortran/libdballef.la dumpmsg_dballe_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(FCLD) \ $(dumpmsg_dballe_FCFLAGS) $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ am__genattr_SOURCES_DIST = genattr.f90 @DO_DBALLEF_TRUE@am_genattr_OBJECTS = genattr-genattr.$(OBJEXT) genattr_OBJECTS = $(am_genattr_OBJECTS) @DO_DBALLEF_TRUE@genattr_DEPENDENCIES = ../fortran/libdballef.la genattr_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(genattr_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__mkmsg_SOURCES_DIST = mkmsg.f90 @DO_DBALLEF_TRUE@am_mkmsg_OBJECTS = mkmsg-mkmsg.$(OBJEXT) mkmsg_OBJECTS = $(am_mkmsg_OBJECTS) @DO_DBALLEF_TRUE@mkmsg_DEPENDENCIES = ../fortran/libdballef.la mkmsg_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(mkmsg_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__mkmsg_sca_SOURCES_DIST = mkmsg-sca.f90 @DO_DBALLEF_TRUE@am_mkmsg_sca_OBJECTS = mkmsg_sca-mkmsg-sca.$(OBJEXT) mkmsg_sca_OBJECTS = $(am_mkmsg_sca_OBJECTS) @DO_DBALLEF_TRUE@mkmsg_sca_DEPENDENCIES = ../fortran/libdballef.la mkmsg_sca_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(mkmsg_sca_FCFLAGS) \ $(FCFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = FCCOMPILE = $(FC) $(AM_FCFLAGS) $(FCFLAGS) LTFCCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(FC) $(AM_FCFLAGS) $(FCFLAGS) AM_V_FC = $(am__v_FC_@AM_V@) am__v_FC_ = $(am__v_FC_@AM_DEFAULT_V@) am__v_FC_0 = @echo " FC " $@; am__v_FC_1 = FCLD = $(FC) FCLINK = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(FCLD) $(AM_FCFLAGS) $(FCFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_FCLD = $(am__v_FCLD_@AM_V@) am__v_FCLD_ = $(am__v_FCLD_@AM_DEFAULT_V@) am__v_FCLD_0 = @echo " FCLD " $@; am__v_FCLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libdballef_la_SOURCES) $(check_attrs_SOURCES) \ $(check_fdballe_SOURCES) $(check_messages_SOURCES) \ $(check_messages_stdinstdout_SOURCES) $(check_missing_SOURCES) \ $(check_missing_msg_SOURCES) $(check_multiplehandler_SOURCES) \ $(check_range_SOURCES) $(check_real0_SOURCES) \ $(check_segfault1_SOURCES) $(check_spiegab_SOURCES) \ $(dump_dballe_SOURCES) $(dumpmsg_dballe_SOURCES) \ $(genattr_SOURCES) $(mkmsg_SOURCES) $(mkmsg_sca_SOURCES) DIST_SOURCES = $(am__libdballef_la_SOURCES_DIST) \ $(am__check_attrs_SOURCES_DIST) \ $(am__check_fdballe_SOURCES_DIST) \ $(am__check_messages_SOURCES_DIST) \ $(am__check_messages_stdinstdout_SOURCES_DIST) \ $(am__check_missing_SOURCES_DIST) \ $(am__check_missing_msg_SOURCES_DIST) \ $(am__check_multiplehandler_SOURCES_DIST) \ $(am__check_range_SOURCES_DIST) \ $(am__check_real0_SOURCES_DIST) \ $(am__check_segfault1_SOURCES_DIST) \ $(am__check_spiegab_SOURCES_DIST) \ $(am__dump_dballe_SOURCES_DIST) \ $(am__dumpmsg_dballe_SOURCES_DIST) $(am__genattr_SOURCES_DIST) \ $(am__mkmsg_SOURCES_DIST) $(am__mkmsg_sca_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__dist_dballeinclude_HEADERS_DIST = dballef.h dballeff.h am__dist_noinst_HEADERS_DIST = handles.h HEADERS = $(dist_dballeinclude_HEADERS) $(dist_noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ $(am__append_2) CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FC = @FC@ FCFLAGS = @FCFLAGS@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDBALLEF_VERSION_INFO = @LIBDBALLEF_VERSION_INFO@ LIBDBALLE_VERSION_INFO = @LIBDBALLE_VERSION_INFO@ LIBOBJS = @LIBOBJS@ LIBPQ_CFLAGS = @LIBPQ_CFLAGS@ LIBPQ_LIBS = @LIBPQ_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ WREPORT_CFLAGS = @WREPORT_CFLAGS@ WREPORT_LIBS = @WREPORT_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_FC = @ac_ct_FC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_doxygen = @have_doxygen@ have_gperf = @have_gperf@ have_latex2html = @have_latex2html@ have_rst2html = @have_rst2html@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mysql_config = @mysql_config@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ tabledir = @tabledir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @DO_DBALLEF_TRUE@AM_CPPFLAGS = -I$(top_srcdir) $(WREPORT_CFLAGS) \ @DO_DBALLEF_TRUE@ $(am__append_1) # libdballef @DO_DBALLEF_TRUE@dballeincludedir = $(includedir)/dballe # Include the F90 interface file as well @DO_DBALLEF_TRUE@dist_dballeinclude_HEADERS = dballef.h dballeff.h @DO_DBALLEF_TRUE@dist_noinst_HEADERS = handles.h @DO_DBALLEF_TRUE@lib_LTLIBRARIES = libdballef.la @DO_DBALLEF_TRUE@libdballef_la_SOURCES = \ @DO_DBALLEF_TRUE@ error.cc \ @DO_DBALLEF_TRUE@ trace.cc \ @DO_DBALLEF_TRUE@ binding.cc @DO_DBALLEF_TRUE@libdballef_la_LIBADD = ../dballe/libdballe.la -lcnf @DO_DBALLEF_TRUE@libdballef_la_LDFLAGS = -version-info @LIBDBALLEF_VERSION_INFO@ # # Unit testing # @DO_DBALLEF_TRUE@TESTS_ENVIRONMENT = $(top_srcdir)/extra/runtest #TESTS = $(check_PROGRAMS) @DO_DBALLEF_TRUE@dbtestlib = test.f90 dbtest.f90 @DO_DBALLEF_TRUE@check_missing_msg_SOURCES = test.f90 check_missing_msg.f90 @DO_DBALLEF_TRUE@check_missing_msg_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_missing_msg_FCFLAGS = -g @DO_DBALLEF_TRUE@check_real0_SOURCES = $(dbtestlib) check_real0.f90 @DO_DBALLEF_TRUE@check_real0_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_real0_FCFLAGS = -g @DO_DBALLEF_TRUE@check_range_SOURCES = $(dbtestlib) check_range.f90 @DO_DBALLEF_TRUE@check_range_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_range_FCFLAGS = -g @DO_DBALLEF_TRUE@check_fdballe_SOURCES = $(dbtestlib) check_fdballe.f90 @DO_DBALLEF_TRUE@check_fdballe_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_fdballe_FCFLAGS = -g @DO_DBALLEF_TRUE@check_attrs_SOURCES = $(dbtestlib) check_attrs.f90 @DO_DBALLEF_TRUE@check_attrs_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_attrs_FCFLAGS = -g @DO_DBALLEF_TRUE@check_missing_SOURCES = $(dbtestlib) check_missing.f90 @DO_DBALLEF_TRUE@check_missing_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_missing_FCFLAGS = -g @DO_DBALLEF_TRUE@check_segfault1_SOURCES = $(dbtestlib) check_segfault1.f90 @DO_DBALLEF_TRUE@check_segfault1_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_segfault1_FCFLAGS = -g @DO_DBALLEF_TRUE@check_spiegab_SOURCES = $(dbtestlib) check_spiegab.f90 @DO_DBALLEF_TRUE@check_spiegab_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_spiegab_FCFLAGS = -g @DO_DBALLEF_TRUE@check_messages_SOURCES = $(dbtestlib) check_messages.f90 @DO_DBALLEF_TRUE@check_messages_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_messages_FCFLAGS = -g @DO_DBALLEF_TRUE@check_messages_stdinstdout_SOURCES = $(dbtestlib) check_messages_stdinstdout.f90 @DO_DBALLEF_TRUE@check_messages_stdinstdout_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_messages_stdinstdout_FCFLAGS = -g @DO_DBALLEF_TRUE@check_multiplehandler_SOURCES = $(dbtestlib) check_multiplehandler.f90 @DO_DBALLEF_TRUE@check_multiplehandler_LDADD = ./libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@check_multiplehandler_FCFLAGS = -g @DO_DBALLEF_TRUE@dumpmsg_dballe_SOURCES = dumpmsg_dballe.f90 @DO_DBALLEF_TRUE@dumpmsg_dballe_LDADD = ../fortran/libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@dumpmsg_dballe_FCFLAGS = -g @DO_DBALLEF_TRUE@mkmsg_SOURCES = mkmsg.f90 @DO_DBALLEF_TRUE@mkmsg_LDADD = ../fortran/libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@mkmsg_FCFLAGS = -g @DO_DBALLEF_TRUE@mkmsg_sca_SOURCES = mkmsg-sca.f90 @DO_DBALLEF_TRUE@mkmsg_sca_LDADD = ../fortran/libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@mkmsg_sca_FCFLAGS = -g @DO_DBALLEF_TRUE@genattr_SOURCES = genattr.f90 @DO_DBALLEF_TRUE@genattr_LDADD = ../fortran/libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@genattr_FCFLAGS = -g @DO_DBALLEF_TRUE@dump_dballe_SOURCES = dump_dballe.f90 @DO_DBALLEF_TRUE@dump_dballe_LDADD = ../fortran/libdballef.la -lcnf -lpopt @DO_DBALLEF_TRUE@dump_dballe_FCFLAGS = -g @DO_DBALLEF_TRUE@EXTRA_DIST = fortran.dox check-utils.h error.h trace.h @DO_DBALLEF_TRUE@CLEANFILES = *.mod all: all-am .SUFFIXES: .SUFFIXES: .cc .f90 .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign fortran/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign fortran/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *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);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libdballef.la: $(libdballef_la_OBJECTS) $(libdballef_la_DEPENDENCIES) $(EXTRA_libdballef_la_DEPENDENCIES) $(AM_V_CXXLD)$(libdballef_la_LINK) $(am_libdballef_la_rpath) $(libdballef_la_OBJECTS) $(libdballef_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 clean-noinstPROGRAMS: @list='$(noinst_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 check_attrs$(EXEEXT): $(check_attrs_OBJECTS) $(check_attrs_DEPENDENCIES) $(EXTRA_check_attrs_DEPENDENCIES) @rm -f check_attrs$(EXEEXT) $(AM_V_FCLD)$(check_attrs_LINK) $(check_attrs_OBJECTS) $(check_attrs_LDADD) $(LIBS) check_fdballe$(EXEEXT): $(check_fdballe_OBJECTS) $(check_fdballe_DEPENDENCIES) $(EXTRA_check_fdballe_DEPENDENCIES) @rm -f check_fdballe$(EXEEXT) $(AM_V_FCLD)$(check_fdballe_LINK) $(check_fdballe_OBJECTS) $(check_fdballe_LDADD) $(LIBS) check_messages$(EXEEXT): $(check_messages_OBJECTS) $(check_messages_DEPENDENCIES) $(EXTRA_check_messages_DEPENDENCIES) @rm -f check_messages$(EXEEXT) $(AM_V_FCLD)$(check_messages_LINK) $(check_messages_OBJECTS) $(check_messages_LDADD) $(LIBS) check_messages_stdinstdout$(EXEEXT): $(check_messages_stdinstdout_OBJECTS) $(check_messages_stdinstdout_DEPENDENCIES) $(EXTRA_check_messages_stdinstdout_DEPENDENCIES) @rm -f check_messages_stdinstdout$(EXEEXT) $(AM_V_FCLD)$(check_messages_stdinstdout_LINK) $(check_messages_stdinstdout_OBJECTS) $(check_messages_stdinstdout_LDADD) $(LIBS) check_missing$(EXEEXT): $(check_missing_OBJECTS) $(check_missing_DEPENDENCIES) $(EXTRA_check_missing_DEPENDENCIES) @rm -f check_missing$(EXEEXT) $(AM_V_FCLD)$(check_missing_LINK) $(check_missing_OBJECTS) $(check_missing_LDADD) $(LIBS) check_missing_msg$(EXEEXT): $(check_missing_msg_OBJECTS) $(check_missing_msg_DEPENDENCIES) $(EXTRA_check_missing_msg_DEPENDENCIES) @rm -f check_missing_msg$(EXEEXT) $(AM_V_FCLD)$(check_missing_msg_LINK) $(check_missing_msg_OBJECTS) $(check_missing_msg_LDADD) $(LIBS) check_multiplehandler$(EXEEXT): $(check_multiplehandler_OBJECTS) $(check_multiplehandler_DEPENDENCIES) $(EXTRA_check_multiplehandler_DEPENDENCIES) @rm -f check_multiplehandler$(EXEEXT) $(AM_V_FCLD)$(check_multiplehandler_LINK) $(check_multiplehandler_OBJECTS) $(check_multiplehandler_LDADD) $(LIBS) check_range$(EXEEXT): $(check_range_OBJECTS) $(check_range_DEPENDENCIES) $(EXTRA_check_range_DEPENDENCIES) @rm -f check_range$(EXEEXT) $(AM_V_FCLD)$(check_range_LINK) $(check_range_OBJECTS) $(check_range_LDADD) $(LIBS) check_real0$(EXEEXT): $(check_real0_OBJECTS) $(check_real0_DEPENDENCIES) $(EXTRA_check_real0_DEPENDENCIES) @rm -f check_real0$(EXEEXT) $(AM_V_FCLD)$(check_real0_LINK) $(check_real0_OBJECTS) $(check_real0_LDADD) $(LIBS) check_segfault1$(EXEEXT): $(check_segfault1_OBJECTS) $(check_segfault1_DEPENDENCIES) $(EXTRA_check_segfault1_DEPENDENCIES) @rm -f check_segfault1$(EXEEXT) $(AM_V_FCLD)$(check_segfault1_LINK) $(check_segfault1_OBJECTS) $(check_segfault1_LDADD) $(LIBS) check_spiegab$(EXEEXT): $(check_spiegab_OBJECTS) $(check_spiegab_DEPENDENCIES) $(EXTRA_check_spiegab_DEPENDENCIES) @rm -f check_spiegab$(EXEEXT) $(AM_V_FCLD)$(check_spiegab_LINK) $(check_spiegab_OBJECTS) $(check_spiegab_LDADD) $(LIBS) dump_dballe$(EXEEXT): $(dump_dballe_OBJECTS) $(dump_dballe_DEPENDENCIES) $(EXTRA_dump_dballe_DEPENDENCIES) @rm -f dump_dballe$(EXEEXT) $(AM_V_FCLD)$(dump_dballe_LINK) $(dump_dballe_OBJECTS) $(dump_dballe_LDADD) $(LIBS) dumpmsg_dballe$(EXEEXT): $(dumpmsg_dballe_OBJECTS) $(dumpmsg_dballe_DEPENDENCIES) $(EXTRA_dumpmsg_dballe_DEPENDENCIES) @rm -f dumpmsg_dballe$(EXEEXT) $(AM_V_FCLD)$(dumpmsg_dballe_LINK) $(dumpmsg_dballe_OBJECTS) $(dumpmsg_dballe_LDADD) $(LIBS) genattr$(EXEEXT): $(genattr_OBJECTS) $(genattr_DEPENDENCIES) $(EXTRA_genattr_DEPENDENCIES) @rm -f genattr$(EXEEXT) $(AM_V_FCLD)$(genattr_LINK) $(genattr_OBJECTS) $(genattr_LDADD) $(LIBS) mkmsg$(EXEEXT): $(mkmsg_OBJECTS) $(mkmsg_DEPENDENCIES) $(EXTRA_mkmsg_DEPENDENCIES) @rm -f mkmsg$(EXEEXT) $(AM_V_FCLD)$(mkmsg_LINK) $(mkmsg_OBJECTS) $(mkmsg_LDADD) $(LIBS) mkmsg-sca$(EXEEXT): $(mkmsg_sca_OBJECTS) $(mkmsg_sca_DEPENDENCIES) $(EXTRA_mkmsg_sca_DEPENDENCIES) @rm -f mkmsg-sca$(EXEEXT) $(AM_V_FCLD)$(mkmsg_sca_LINK) $(mkmsg_sca_OBJECTS) $(mkmsg_sca_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binding.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< .f90.o: $(AM_V_FC)$(FCCOMPILE) -c -o $@ $< .f90.obj: $(AM_V_FC)$(FCCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .f90.lo: $(AM_V_FC)$(LTFCCOMPILE) -c -o $@ $< check_attrs-test.o: test.f90 $(AM_V_FC)$(FC) $(check_attrs_FCFLAGS) $(FCFLAGS) -c -o check_attrs-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_attrs-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_attrs_FCFLAGS) $(FCFLAGS) -c -o check_attrs-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_attrs-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_attrs_FCFLAGS) $(FCFLAGS) -c -o check_attrs-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_attrs-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_attrs_FCFLAGS) $(FCFLAGS) -c -o check_attrs-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_attrs-check_attrs.o: check_attrs.f90 $(AM_V_FC)$(FC) $(check_attrs_FCFLAGS) $(FCFLAGS) -c -o check_attrs-check_attrs.o `test -f 'check_attrs.f90' || echo '$(srcdir)/'`check_attrs.f90 check_attrs-check_attrs.obj: check_attrs.f90 $(AM_V_FC)$(FC) $(check_attrs_FCFLAGS) $(FCFLAGS) -c -o check_attrs-check_attrs.obj `if test -f 'check_attrs.f90'; then $(CYGPATH_W) 'check_attrs.f90'; else $(CYGPATH_W) '$(srcdir)/check_attrs.f90'; fi` check_fdballe-test.o: test.f90 $(AM_V_FC)$(FC) $(check_fdballe_FCFLAGS) $(FCFLAGS) -c -o check_fdballe-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_fdballe-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_fdballe_FCFLAGS) $(FCFLAGS) -c -o check_fdballe-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_fdballe-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_fdballe_FCFLAGS) $(FCFLAGS) -c -o check_fdballe-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_fdballe-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_fdballe_FCFLAGS) $(FCFLAGS) -c -o check_fdballe-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_fdballe-check_fdballe.o: check_fdballe.f90 $(AM_V_FC)$(FC) $(check_fdballe_FCFLAGS) $(FCFLAGS) -c -o check_fdballe-check_fdballe.o `test -f 'check_fdballe.f90' || echo '$(srcdir)/'`check_fdballe.f90 check_fdballe-check_fdballe.obj: check_fdballe.f90 $(AM_V_FC)$(FC) $(check_fdballe_FCFLAGS) $(FCFLAGS) -c -o check_fdballe-check_fdballe.obj `if test -f 'check_fdballe.f90'; then $(CYGPATH_W) 'check_fdballe.f90'; else $(CYGPATH_W) '$(srcdir)/check_fdballe.f90'; fi` check_messages-test.o: test.f90 $(AM_V_FC)$(FC) $(check_messages_FCFLAGS) $(FCFLAGS) -c -o check_messages-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_messages-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_messages_FCFLAGS) $(FCFLAGS) -c -o check_messages-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_messages-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_messages_FCFLAGS) $(FCFLAGS) -c -o check_messages-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_messages-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_messages_FCFLAGS) $(FCFLAGS) -c -o check_messages-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_messages-check_messages.o: check_messages.f90 $(AM_V_FC)$(FC) $(check_messages_FCFLAGS) $(FCFLAGS) -c -o check_messages-check_messages.o `test -f 'check_messages.f90' || echo '$(srcdir)/'`check_messages.f90 check_messages-check_messages.obj: check_messages.f90 $(AM_V_FC)$(FC) $(check_messages_FCFLAGS) $(FCFLAGS) -c -o check_messages-check_messages.obj `if test -f 'check_messages.f90'; then $(CYGPATH_W) 'check_messages.f90'; else $(CYGPATH_W) '$(srcdir)/check_messages.f90'; fi` check_messages_stdinstdout-test.o: test.f90 $(AM_V_FC)$(FC) $(check_messages_stdinstdout_FCFLAGS) $(FCFLAGS) -c -o check_messages_stdinstdout-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_messages_stdinstdout-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_messages_stdinstdout_FCFLAGS) $(FCFLAGS) -c -o check_messages_stdinstdout-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_messages_stdinstdout-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_messages_stdinstdout_FCFLAGS) $(FCFLAGS) -c -o check_messages_stdinstdout-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_messages_stdinstdout-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_messages_stdinstdout_FCFLAGS) $(FCFLAGS) -c -o check_messages_stdinstdout-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_messages_stdinstdout-check_messages_stdinstdout.o: check_messages_stdinstdout.f90 $(AM_V_FC)$(FC) $(check_messages_stdinstdout_FCFLAGS) $(FCFLAGS) -c -o check_messages_stdinstdout-check_messages_stdinstdout.o `test -f 'check_messages_stdinstdout.f90' || echo '$(srcdir)/'`check_messages_stdinstdout.f90 check_messages_stdinstdout-check_messages_stdinstdout.obj: check_messages_stdinstdout.f90 $(AM_V_FC)$(FC) $(check_messages_stdinstdout_FCFLAGS) $(FCFLAGS) -c -o check_messages_stdinstdout-check_messages_stdinstdout.obj `if test -f 'check_messages_stdinstdout.f90'; then $(CYGPATH_W) 'check_messages_stdinstdout.f90'; else $(CYGPATH_W) '$(srcdir)/check_messages_stdinstdout.f90'; fi` check_missing-test.o: test.f90 $(AM_V_FC)$(FC) $(check_missing_FCFLAGS) $(FCFLAGS) -c -o check_missing-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_missing-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_missing_FCFLAGS) $(FCFLAGS) -c -o check_missing-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_missing-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_missing_FCFLAGS) $(FCFLAGS) -c -o check_missing-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_missing-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_missing_FCFLAGS) $(FCFLAGS) -c -o check_missing-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_missing-check_missing.o: check_missing.f90 $(AM_V_FC)$(FC) $(check_missing_FCFLAGS) $(FCFLAGS) -c -o check_missing-check_missing.o `test -f 'check_missing.f90' || echo '$(srcdir)/'`check_missing.f90 check_missing-check_missing.obj: check_missing.f90 $(AM_V_FC)$(FC) $(check_missing_FCFLAGS) $(FCFLAGS) -c -o check_missing-check_missing.obj `if test -f 'check_missing.f90'; then $(CYGPATH_W) 'check_missing.f90'; else $(CYGPATH_W) '$(srcdir)/check_missing.f90'; fi` check_missing_msg-test.o: test.f90 $(AM_V_FC)$(FC) $(check_missing_msg_FCFLAGS) $(FCFLAGS) -c -o check_missing_msg-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_missing_msg-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_missing_msg_FCFLAGS) $(FCFLAGS) -c -o check_missing_msg-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_missing_msg-check_missing_msg.o: check_missing_msg.f90 $(AM_V_FC)$(FC) $(check_missing_msg_FCFLAGS) $(FCFLAGS) -c -o check_missing_msg-check_missing_msg.o `test -f 'check_missing_msg.f90' || echo '$(srcdir)/'`check_missing_msg.f90 check_missing_msg-check_missing_msg.obj: check_missing_msg.f90 $(AM_V_FC)$(FC) $(check_missing_msg_FCFLAGS) $(FCFLAGS) -c -o check_missing_msg-check_missing_msg.obj `if test -f 'check_missing_msg.f90'; then $(CYGPATH_W) 'check_missing_msg.f90'; else $(CYGPATH_W) '$(srcdir)/check_missing_msg.f90'; fi` check_multiplehandler-test.o: test.f90 $(AM_V_FC)$(FC) $(check_multiplehandler_FCFLAGS) $(FCFLAGS) -c -o check_multiplehandler-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_multiplehandler-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_multiplehandler_FCFLAGS) $(FCFLAGS) -c -o check_multiplehandler-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_multiplehandler-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_multiplehandler_FCFLAGS) $(FCFLAGS) -c -o check_multiplehandler-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_multiplehandler-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_multiplehandler_FCFLAGS) $(FCFLAGS) -c -o check_multiplehandler-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_multiplehandler-check_multiplehandler.o: check_multiplehandler.f90 $(AM_V_FC)$(FC) $(check_multiplehandler_FCFLAGS) $(FCFLAGS) -c -o check_multiplehandler-check_multiplehandler.o `test -f 'check_multiplehandler.f90' || echo '$(srcdir)/'`check_multiplehandler.f90 check_multiplehandler-check_multiplehandler.obj: check_multiplehandler.f90 $(AM_V_FC)$(FC) $(check_multiplehandler_FCFLAGS) $(FCFLAGS) -c -o check_multiplehandler-check_multiplehandler.obj `if test -f 'check_multiplehandler.f90'; then $(CYGPATH_W) 'check_multiplehandler.f90'; else $(CYGPATH_W) '$(srcdir)/check_multiplehandler.f90'; fi` check_range-test.o: test.f90 $(AM_V_FC)$(FC) $(check_range_FCFLAGS) $(FCFLAGS) -c -o check_range-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_range-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_range_FCFLAGS) $(FCFLAGS) -c -o check_range-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_range-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_range_FCFLAGS) $(FCFLAGS) -c -o check_range-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_range-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_range_FCFLAGS) $(FCFLAGS) -c -o check_range-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_range-check_range.o: check_range.f90 $(AM_V_FC)$(FC) $(check_range_FCFLAGS) $(FCFLAGS) -c -o check_range-check_range.o `test -f 'check_range.f90' || echo '$(srcdir)/'`check_range.f90 check_range-check_range.obj: check_range.f90 $(AM_V_FC)$(FC) $(check_range_FCFLAGS) $(FCFLAGS) -c -o check_range-check_range.obj `if test -f 'check_range.f90'; then $(CYGPATH_W) 'check_range.f90'; else $(CYGPATH_W) '$(srcdir)/check_range.f90'; fi` check_real0-test.o: test.f90 $(AM_V_FC)$(FC) $(check_real0_FCFLAGS) $(FCFLAGS) -c -o check_real0-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_real0-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_real0_FCFLAGS) $(FCFLAGS) -c -o check_real0-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_real0-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_real0_FCFLAGS) $(FCFLAGS) -c -o check_real0-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_real0-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_real0_FCFLAGS) $(FCFLAGS) -c -o check_real0-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_real0-check_real0.o: check_real0.f90 $(AM_V_FC)$(FC) $(check_real0_FCFLAGS) $(FCFLAGS) -c -o check_real0-check_real0.o `test -f 'check_real0.f90' || echo '$(srcdir)/'`check_real0.f90 check_real0-check_real0.obj: check_real0.f90 $(AM_V_FC)$(FC) $(check_real0_FCFLAGS) $(FCFLAGS) -c -o check_real0-check_real0.obj `if test -f 'check_real0.f90'; then $(CYGPATH_W) 'check_real0.f90'; else $(CYGPATH_W) '$(srcdir)/check_real0.f90'; fi` check_segfault1-test.o: test.f90 $(AM_V_FC)$(FC) $(check_segfault1_FCFLAGS) $(FCFLAGS) -c -o check_segfault1-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_segfault1-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_segfault1_FCFLAGS) $(FCFLAGS) -c -o check_segfault1-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_segfault1-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_segfault1_FCFLAGS) $(FCFLAGS) -c -o check_segfault1-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_segfault1-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_segfault1_FCFLAGS) $(FCFLAGS) -c -o check_segfault1-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_segfault1-check_segfault1.o: check_segfault1.f90 $(AM_V_FC)$(FC) $(check_segfault1_FCFLAGS) $(FCFLAGS) -c -o check_segfault1-check_segfault1.o `test -f 'check_segfault1.f90' || echo '$(srcdir)/'`check_segfault1.f90 check_segfault1-check_segfault1.obj: check_segfault1.f90 $(AM_V_FC)$(FC) $(check_segfault1_FCFLAGS) $(FCFLAGS) -c -o check_segfault1-check_segfault1.obj `if test -f 'check_segfault1.f90'; then $(CYGPATH_W) 'check_segfault1.f90'; else $(CYGPATH_W) '$(srcdir)/check_segfault1.f90'; fi` check_spiegab-test.o: test.f90 $(AM_V_FC)$(FC) $(check_spiegab_FCFLAGS) $(FCFLAGS) -c -o check_spiegab-test.o `test -f 'test.f90' || echo '$(srcdir)/'`test.f90 check_spiegab-test.obj: test.f90 $(AM_V_FC)$(FC) $(check_spiegab_FCFLAGS) $(FCFLAGS) -c -o check_spiegab-test.obj `if test -f 'test.f90'; then $(CYGPATH_W) 'test.f90'; else $(CYGPATH_W) '$(srcdir)/test.f90'; fi` check_spiegab-dbtest.o: dbtest.f90 $(AM_V_FC)$(FC) $(check_spiegab_FCFLAGS) $(FCFLAGS) -c -o check_spiegab-dbtest.o `test -f 'dbtest.f90' || echo '$(srcdir)/'`dbtest.f90 check_spiegab-dbtest.obj: dbtest.f90 $(AM_V_FC)$(FC) $(check_spiegab_FCFLAGS) $(FCFLAGS) -c -o check_spiegab-dbtest.obj `if test -f 'dbtest.f90'; then $(CYGPATH_W) 'dbtest.f90'; else $(CYGPATH_W) '$(srcdir)/dbtest.f90'; fi` check_spiegab-check_spiegab.o: check_spiegab.f90 $(AM_V_FC)$(FC) $(check_spiegab_FCFLAGS) $(FCFLAGS) -c -o check_spiegab-check_spiegab.o `test -f 'check_spiegab.f90' || echo '$(srcdir)/'`check_spiegab.f90 check_spiegab-check_spiegab.obj: check_spiegab.f90 $(AM_V_FC)$(FC) $(check_spiegab_FCFLAGS) $(FCFLAGS) -c -o check_spiegab-check_spiegab.obj `if test -f 'check_spiegab.f90'; then $(CYGPATH_W) 'check_spiegab.f90'; else $(CYGPATH_W) '$(srcdir)/check_spiegab.f90'; fi` dump_dballe-dump_dballe.o: dump_dballe.f90 $(AM_V_FC)$(FC) $(dump_dballe_FCFLAGS) $(FCFLAGS) -c -o dump_dballe-dump_dballe.o `test -f 'dump_dballe.f90' || echo '$(srcdir)/'`dump_dballe.f90 dump_dballe-dump_dballe.obj: dump_dballe.f90 $(AM_V_FC)$(FC) $(dump_dballe_FCFLAGS) $(FCFLAGS) -c -o dump_dballe-dump_dballe.obj `if test -f 'dump_dballe.f90'; then $(CYGPATH_W) 'dump_dballe.f90'; else $(CYGPATH_W) '$(srcdir)/dump_dballe.f90'; fi` dumpmsg_dballe-dumpmsg_dballe.o: dumpmsg_dballe.f90 $(AM_V_FC)$(FC) $(dumpmsg_dballe_FCFLAGS) $(FCFLAGS) -c -o dumpmsg_dballe-dumpmsg_dballe.o `test -f 'dumpmsg_dballe.f90' || echo '$(srcdir)/'`dumpmsg_dballe.f90 dumpmsg_dballe-dumpmsg_dballe.obj: dumpmsg_dballe.f90 $(AM_V_FC)$(FC) $(dumpmsg_dballe_FCFLAGS) $(FCFLAGS) -c -o dumpmsg_dballe-dumpmsg_dballe.obj `if test -f 'dumpmsg_dballe.f90'; then $(CYGPATH_W) 'dumpmsg_dballe.f90'; else $(CYGPATH_W) '$(srcdir)/dumpmsg_dballe.f90'; fi` genattr-genattr.o: genattr.f90 $(AM_V_FC)$(FC) $(genattr_FCFLAGS) $(FCFLAGS) -c -o genattr-genattr.o `test -f 'genattr.f90' || echo '$(srcdir)/'`genattr.f90 genattr-genattr.obj: genattr.f90 $(AM_V_FC)$(FC) $(genattr_FCFLAGS) $(FCFLAGS) -c -o genattr-genattr.obj `if test -f 'genattr.f90'; then $(CYGPATH_W) 'genattr.f90'; else $(CYGPATH_W) '$(srcdir)/genattr.f90'; fi` mkmsg-mkmsg.o: mkmsg.f90 $(AM_V_FC)$(FC) $(mkmsg_FCFLAGS) $(FCFLAGS) -c -o mkmsg-mkmsg.o `test -f 'mkmsg.f90' || echo '$(srcdir)/'`mkmsg.f90 mkmsg-mkmsg.obj: mkmsg.f90 $(AM_V_FC)$(FC) $(mkmsg_FCFLAGS) $(FCFLAGS) -c -o mkmsg-mkmsg.obj `if test -f 'mkmsg.f90'; then $(CYGPATH_W) 'mkmsg.f90'; else $(CYGPATH_W) '$(srcdir)/mkmsg.f90'; fi` mkmsg_sca-mkmsg-sca.o: mkmsg-sca.f90 $(AM_V_FC)$(FC) $(mkmsg_sca_FCFLAGS) $(FCFLAGS) -c -o mkmsg_sca-mkmsg-sca.o `test -f 'mkmsg-sca.f90' || echo '$(srcdir)/'`mkmsg-sca.f90 mkmsg_sca-mkmsg-sca.obj: mkmsg-sca.f90 $(AM_V_FC)$(FC) $(mkmsg_sca_FCFLAGS) $(FCFLAGS) -c -o mkmsg_sca-mkmsg-sca.obj `if test -f 'mkmsg-sca.f90'; then $(CYGPATH_W) 'mkmsg-sca.f90'; else $(CYGPATH_W) '$(srcdir)/mkmsg-sca.f90'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_dballeincludeHEADERS: $(dist_dballeinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(dist_dballeinclude_HEADERS)'; test -n "$(dballeincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(dballeincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(dballeincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(dballeincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(dballeincludedir)" || exit $$?; \ done uninstall-dist_dballeincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(dist_dballeinclude_HEADERS)'; test -n "$(dballeincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(dballeincludedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @DO_DBALLEF_FALSE@check-local: check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(dballeincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_dballeincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_dballeincludeHEADERS \ uninstall-libLTLIBRARIES .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 clean-noinstPROGRAMS 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-dist_dballeincludeHEADERS 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-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am \ uninstall-dist_dballeincludeHEADERS uninstall-libLTLIBRARIES .PRECIOUS: Makefile @DO_DBALLEF_TRUE@check-local: @DO_DBALLEF_TRUE@ for test in $(check_PROGRAMS); do \ @DO_DBALLEF_TRUE@ $(TESTS_ENVIRONMENT) $$test ; \ @DO_DBALLEF_TRUE@ done # 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: dballe-7.7/fortran/check_messages_stdinstdout.f900000644000175000017500000000316212652630043017141 00000000000000 program check_fdballe ! ***************************************** ! * Test suite for DBALLE Fortran bindings ! ***************************************** use dbtest include "dballeff.h" integer :: dbahandle, handle,i,i1,i2,i3,i4,i5,i6,ival,saved_id real :: rval double precision :: dval character (len=10) :: param character (len=255) :: cval character (len=512) :: infile external :: testcb logical :: status ! call fdba_error_set_callback(0, testcb, 2, i) ier = idba_presentati(dbahandle, "mem:", char(0), char(0)) call ensure_no_error("presentati") ier = idba_preparati(dbahandle, handle, "write", "write", "write") call ensure_no_error("preparati") ! Database login ier = idba_messages_open_input(handle, "", "rb", "BUFR", .true.) call ensure_no_error("messages_open_input") ier = idba_messages_open_output(handle, "", "wb", "BUFR") call ensure_no_error("messages_open_output") ! Query the first message/subset ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 1") call ensure("messages_read_next result 1", status) ier = idba_messages_write_next(handle, "") call ensure_no_error("messages_write_next 1") ier = idba_fatto(handle) call ensure_no_error("fatto") ier = idba_arrivederci(dbahandle) call ensure_no_error("arrivederci") ! If we made it so far, exit with no error print*,"check_messages_stdinstdout: all tests succeed." call exit (0) end program include "check-utils.h" dballe-7.7/fortran/check-utils.h0000644000175000017500000000101512652630043013570 00000000000000!!! ******************** !!! * Utility functions !!! ******************** subroutine testcb(val) integer :: val character (len=1000) :: buf ier = idba_error_code() if (ier.ne.0) then print *,ier," testcb in ",val call idba_error_message(buf) print *,trim(buf) call idba_error_context(buf) print *,trim(buf) call idba_error_details(buf) print *,trim(buf) call exit (1) end if return endsubroutine testcb dballe-7.7/fortran/genattr.f900000644000175000017500000000370112652630043013174 00000000000000program tmp implicit none INCLUDE "dballef.h" integer,parameter :: nvar=5 real :: field(nvar),obsinc(nvar) character(len=6) :: var(nvar) INTEGER :: handle,handle_err,ana_id,debug,i ! gestione degli errori call idba_error_set_callback(0,idba_default_error_handler,debug,handle_err) call idba_messaggi(handle, "tmp.bufr", "w", "BUFR") ! vital statistics data call idba_setcontextana (handle) call idba_set (handle,"rep_memo","generic") call idba_set (handle,"lat",44.5) call idba_set (handle,"lon",10.0) call idba_set (handle,"mobile",0) call idba_set (handle,"block",16) call idba_set (handle,"station",144) !!!! e' cosi' per compatibilita' db call idba_prendilo (handle) call idba_enqi (handle,"ana_id",ana_id) call idba_unsetall (handle) call idba_setc (handle,"rep_memo","generic") call idba_seti (handle,"ana_id",ana_id) !!!! call idba_settimerange (handle,254,0,0) call idba_setdate (handle,2010,04,11,12,0,0) call idba_setlevel (handle,100,50000,0,0) var(1)="B11003" var(2)="B11004" var(3)="B12101" var(4)="B13003" var(5)="B07004" field(1)=5.5 field(2)=6.6 field(3)=273.15 field(4)=50. field(5)=55000 obsinc(1)=.5 obsinc(2)=.6 obsinc(3)=10. obsinc(4)=5. obsinc(5)=100. call idba_set(handle,"B08001",1) call idba_prendilo(handle) !call idba_unset(handle,"B08001") print *,"-------------------" ! cicle on 5 variables to write original data and obsevation increments do i=1,nvar print *,var(i),field(i),obsinc(i) ! add or rewrite new data call idba_set(handle,var(i),field(i)) call idba_prendilo(handle) call idba_set(handle,"*B33198",obsinc(i)) call idba_critica(handle) call idba_unset(handle,"*B33198") call idba_unset(handle,var(i)) end do call idba_set(handle,'query',"message generic") call idba_prendilo (handle) ! end session and connection call idba_fatto(handle) end program tmp dballe-7.7/fortran/dballef.h0000644000175000017500000002215412652630043012755 00000000000000 ! ! Interface file for DB-ALLe ! ! Copyright (C) 2005,2006 ARPA-SIM ! ! This program is free software; you can redistribute it and/or modify ! it under the terms of the GNU General Public License as published by ! the Free Software Foundation; either version 2 of the License. ! ! This program is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! GNU General Public License for more details. ! ! You should have received a copy of the GNU General Public License ! along with this program; if not, write to the Free Software ! Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ! ! Author: Enrico Zini ! ! TODO: function o subroutine? ! missing value INTEGER, PARAMETER :: & dba_int_b = SELECTED_INT_KIND(1), & ! Byte integer dba_int_s = SELECTED_INT_KIND(4), & ! Short integer dba_int_l = SELECTED_INT_KIND(8) ! Long integer INTEGER, PARAMETER :: & dba_fp_s = SELECTED_REAL_KIND(6), & ! Single precision dba_fp_d = SELECTED_REAL_KIND(15) ! Double precision REAL, PARAMETER :: DBA_MVR = HUGE(1.0) !REAL(dba_kind=dba_fp_s), PARAMETER :: = HUGE(1.0_dba_fp_s) REAL(kind=dba_fp_d), PARAMETER :: DBA_MVD = HUGE(1.0_dba_fp_d) !REAL(kind=dba_fp_d), PARAMETER :: DBA_MVD = 1.79769D308 INTEGER, PARAMETER :: DBA_MVI = HUGE(0) INTEGER(kind=dba_int_b), PARAMETER :: DBA_MVB = HUGE(0_dba_int_b) CHARACTER(len=1), PARAMETER :: DBA_MVC = char(0) ! Get/Set routines interface idba_enq subroutine idba_enqb(handle,param,value) integer, intent(in) :: handle integer (kind=1),intent(out) :: value character (len=*), intent(in) :: param end subroutine idba_enqb subroutine idba_enqi(handle,param,value) integer, intent(in) :: handle integer, intent(out) :: value character (len=*), intent(in) :: param end subroutine idba_enqi subroutine idba_enqr(handle,param,value) integer, intent(in) :: handle real, intent(out) :: value character (len=*), intent(in) :: param end subroutine idba_enqr subroutine idba_enqd(handle,param,value) integer, intent(in) :: handle double precision, intent(out) :: value character (len=*), intent(in) :: param end subroutine idba_enqd subroutine idba_enqc(handle,param,value) integer, intent(in) :: handle character (len=*), intent(in) :: param character (len=*), intent(out) :: value end subroutine idba_enqc end interface interface idba_set subroutine idba_setb(handle,param,value) integer, intent(in) :: handle integer (kind=1), intent(in) :: value character (len=*), intent(in) :: param end subroutine idba_setb subroutine idba_seti(handle,param,value) integer, intent(in) :: handle,value character (len=*), intent(in) :: param end subroutine idba_seti subroutine idba_setr(handle,param,value) integer, intent(in) :: handle real, intent(in) :: value character (len=*), intent(in) :: param end subroutine idba_setr subroutine idba_setd(handle,param,value) integer, intent(in) :: handle double precision, intent(in) :: value character (len=*), intent(in) :: param end subroutine idba_setd subroutine idba_setc(handle,param,value) integer, intent(in) :: handle character (len=*), intent(in) :: param,value end subroutine idba_setc end interface interface ! Error handling routines integer function idba_error_code() end function idba_error_code subroutine idba_error_message(message) character (len=*), intent(out) :: message end subroutine idba_error_message subroutine idba_error_context(message) character (len=*), intent(out) :: message end subroutine idba_error_context subroutine idba_error_details(message) character (len=*), intent(out) :: message end subroutine idba_error_details subroutine idba_error_set_callback(code,func,data,handle) integer, intent(in) :: code external :: func integer, intent(in) :: data integer, intent(out) :: handle end subroutine idba_error_set_callback subroutine idba_error_remove_callback(handle) integer, intent(in) :: handle end subroutine idba_error_remove_callback integer function idba_default_error_handler(debug) logical, intent(in) :: debug end function idba_default_error_handler integer function idba_error_handler_tolerating_overflows(debug) logical, intent(in) :: debug end function idba_error_handler_tolerating_overflows ! Init/Shutdown routines subroutine idba_presentati(dbahandle, dsn, user, password) integer, intent(out) :: dbahandle character (len=*), intent(in) :: dsn,user,password end subroutine idba_presentati subroutine idba_arrivederci(dbahandle) integer, intent(in) :: dbahandle end subroutine idba_arrivederci subroutine idba_preparati(dbahandle, handle, anaflag, dataflag, attrflag) integer, intent(in) :: dbahandle integer, intent(out) :: handle character (len=*), intent(in) :: anaflag,dataflag,attrflag end subroutine idba_preparati subroutine idba_messaggi(handle, filename, mode, type) integer, intent(out) :: handle character (len=*), intent(in) :: filename,mode,type end subroutine idba_messaggi subroutine idba_fatto(handle) integer, intent(in) :: handle end subroutine idba_fatto subroutine idba_unset(handle,param) integer, intent(in) :: handle character (len=*), intent(in) :: param end subroutine idba_unset subroutine idba_unsetall(handle) integer, intent(in) :: handle end subroutine idba_unsetall subroutine idba_setcontextana(handle) integer, intent(in) :: handle end subroutine idba_setcontextana subroutine idba_enqlevel(handle,ltype1,l1,ltype2,l2) integer, intent(in) :: handle integer, intent(out) :: ltype1,l1,ltype2,l2 end subroutine idba_enqlevel subroutine idba_setlevel(handle,ltype1,l1,ltype2,l2) integer, intent(in) :: handle,ltype1,l1,ltype2,l2 end subroutine idba_setlevel subroutine idba_enqtimerange(handle,ptype,p1,p2) integer, intent(in) :: handle integer, intent(out) :: ptype,p1,p2 end subroutine idba_enqtimerange subroutine idba_settimerange(handle,ptype,p1,p2) integer, intent(in) :: handle,ptype,p1,p2 end subroutine idba_settimerange subroutine idba_enqdate(handle,year,month,day,hour,min,sec) integer, intent(in) :: handle integer, intent(out) :: year,month,day,hour,min,sec end subroutine idba_enqdate subroutine idba_setdate(handle,year,month,day,hour,min,sec) integer, intent(in) :: handle,year,month,day,hour,min,sec end subroutine idba_setdate subroutine idba_setdatemin(handle,year,month,day,hour,min,sec) integer, intent(in) :: handle,year,month,day,hour,min,sec end subroutine idba_setdatemin subroutine idba_setdatemax(handle,year,month,day,hour,min,sec) integer, intent(in) :: handle,year,month,day,hour,min,sec end subroutine idba_setdatemax ! Action routines subroutine idba_scopa(handle, repinfofile) integer, intent(in) :: handle character (len=*), intent(in) :: repinfofile end subroutine idba_scopa subroutine idba_quantesono(handle, count) integer, intent(in) :: handle integer, intent(out) :: count end subroutine idba_quantesono subroutine idba_elencamele(handle) integer, intent(in) :: handle end subroutine idba_elencamele subroutine idba_voglioquesto(handle, count) integer, intent(in) :: handle integer, intent(out) :: count end subroutine idba_voglioquesto subroutine idba_dammelo(handle,param) integer, intent(in) :: handle character (len=*), intent(out) :: param end subroutine idba_dammelo subroutine idba_prendilo(handle) integer, intent(in) :: handle end subroutine idba_prendilo subroutine idba_dimenticami(handle) integer, intent(in) :: handle end subroutine idba_dimenticami subroutine idba_voglioancora(handle, count) integer, intent(in) :: handle integer, intent(out) :: count end subroutine idba_voglioancora subroutine idba_ancora(handle,param) integer, intent(in) :: handle character (len=*), intent(out) :: param end subroutine idba_ancora subroutine idba_critica(handle) integer, intent(in) :: handle end subroutine idba_critica subroutine idba_scusa(handle) integer, intent(in) :: handle end subroutine idba_scusa ! Pretty printing routines subroutine idba_spiegal(handle,ltype1,l1,ltype2,l2,result) integer, intent(in) :: handle,ltype1,l1,ltype2,l2 character (len=*), intent(out) :: result end subroutine idba_spiegal subroutine idba_spiegat(handle,ptype,p1,p2,result) integer, intent(in) :: handle,ptype,p1,p2 character (len=*), intent(out) :: result end subroutine idba_spiegat subroutine idba_spiegab(handle,varcode,var,result) integer, intent(in) :: handle character (len=*), intent(in) :: varcode,var character (len=*), intent(out) :: result end subroutine idba_spiegab end interface dballe-7.7/fortran/check_segfault1.f900000644000175000017500000000202012652630043014551 00000000000000program test integer :: idbhandle1,handle1 integer :: i,anaid integer :: error_handle include "dballef.h" call idba_error_set_callback(0, idba_default_error_handler, 42, error_handle) call idba_presentati(idbhandle1,"sqlite:tmp.sqlite","","") call idba_preparati (idbhandle1,handle1,"write","write","write") call idba_scopa (handle1, "") call idba_fatto(handle1) call idba_arrivederci(idbhandle1) do i = 1, 1030 call idba_presentati(idbhandle1,"sqlite:tmp.sqlite","","") ! print *,"Presentati",idbhandle1 call idba_preparati (idbhandle1,handle1,"write","write","write") ! print *,"Preparati",handle1 ! Insert data about a station call idba_set (handle1, "rep_memo", "synop") call idba_set (handle1, "lat", 11.345) call idba_set (handle1, "lon", 44.678) call idba_set (handle1, "height", 23.0) call idba_setcontextana (handle1); call idba_prendilo (handle1) ! print *,"Fatto",handle1 call idba_fatto(handle1) ! print *,"Arrivederci",idbhandle1 call idba_arrivederci(idbhandle1) end do end program test dballe-7.7/fortran/error.cc0000644000175000017500000001500212652630043012645 00000000000000/* * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ /** @file * @ingroup fortranfull * Error inspection functions for Dballe. * * These funtions closely wrap the Dballe functions in dba_error.h */ #include "handles.h" #include "trace.h" #include #include #include #include extern "C" { #include } #define MAX_CALLBACKS 50 using namespace wreport; namespace { typedef void (*fdba_error_callback)(INTEGER(data)); struct HErrcb : public dballe::fortran::HBase { ErrorCode error; fdba_error_callback cb; int data; void start() { dballe::fortran::HBase::start(); } void stop() { dballe::fortran::HBase::stop(); } // Check if this callback should be triggered by this error code // If it should, invoke the callback void check_invoke(ErrorCode code) { if (error == 0 || error == code) cb(&data); } }; struct dballe::fortran::Handler herr; static ErrorCode last_err_code = WR_ERR_NONE; static char last_err_msg[1024]; } namespace dballe { namespace fortran { static int usage_refcount = 0; void error_init() { if (usage_refcount > 0) return; herr.init("Error Handling", "MAX_CALLBACKS"); ++usage_refcount; } int error(wreport::error& e) { IF_TRACING(log_error(e)); last_err_code = e.code(); strncpy(last_err_msg, e.what(), 1024); size_t todo = herr.in_use; for (int i = 0; todo && i < MAX_CALLBACKS; ++i) if (herr.records[i].used) { herr.records[i].check_invoke(last_err_code); --todo; } return 1; } int success() { last_err_code = WR_ERR_NONE; last_err_msg[0] = 0; return 0; } } } using namespace dballe; extern "C" { // FDBA_HANDLE_BODY(errcb, MAX_CALLBACKS, "Error handling callbacks") /** * Return the error code for the last error that happened * * See @ref dba_error_code() * * @return * The error code. Please see the documentation of ::dba_err_code for the * possible values. */ F77_INTEGER_FUNCTION(idba_error_code)() { return last_err_code; } /** * Return the error message for the last error that happened. * * The error message is just a description of the error code. To see more * details of the specific condition that caused the error, use * fdba_error_context() and fdba_error_details() * * See @ref dba_error_message() * * @param message * The string holding the error messag. If the string is not long enough, it * will be truncated. */ F77_SUBROUTINE(idba_error_message)(CHARACTER(message) TRAIL(message)) { GENPTR_CHARACTER(message) cnfExprt(last_err_msg, message, message_length); } /** * Return a string describing the context in which the error happened. * * This string describes what the code that failed was trying to do. * * See @ref dba_error_context() * * @param message * The string holding the error context. If the string is not long enough, * it will be truncated. */ F77_SUBROUTINE(idba_error_context)(CHARACTER(message) TRAIL(message)) { GENPTR_CHARACTER(message) cnfExprt("", message, message_length); } /** * Return a string with additional details about the error. * * This string contains additional details about the error in case the code was * able to get extra informations about it, for example by querying the error * functions of an underlying module. * * See @ref dba_error_details() * * @param message * The string holding the error details. If the string is not long enough, * it will be truncated. */ F77_SUBROUTINE(idba_error_details)(CHARACTER(message) TRAIL(message)) { GENPTR_CHARACTER(message) cnfExprt("", message, message_length); } /** * Set a callback to be invoked when an error of a specific kind happens. * * @param code * The error code (See @ref ::dba_err_code) of the error that triggers this * callback. If DBA_ERR_NONE is used, then the callback is invoked on all * errors. * @param func * The function to be called. * @param data * An arbitrary integer data that is passed verbatim to the callback function * when invoked. * @retval handle * A handle that can be used to remove the callback * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_error_set_callback)( INTEGER(code), SUBROUTINE(func), INTEGER(data), INTEGER(handle)) { GENPTR_INTEGER(code) GENPTR_SUBROUTINE(func) GENPTR_INTEGER(data) GENPTR_INTEGER(handle) // Initialise the error library in case it has not been done yet fortran::error_init(); *handle = herr.request(); HErrcb& h = herr.get(*handle); h.error = (ErrorCode)*code; h.cb = (fdba_error_callback)func; h.data = *data; return fortran::success(); } /** * Remove a callback set previously. * * @param handle * The handle previously returned by idba_error_set_callback * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_error_remove_callback)(INTEGER(handle)) { GENPTR_INTEGER(handle) herr.release(*handle); return fortran::success(); } /** * Default callback that prints a message and exits. * * The message is printed only if a non-zero value is supplied as user data */ F77_INTEGER_FUNCTION(idba_default_error_handler)(INTEGER(debug)) { GENPTR_INTEGER(debug) if (*debug) fprintf(stderr, "DB-All.e error %d: %s\n", last_err_code, last_err_msg); exit(1); } F77_INTEGER_FUNCTION(idba_default_error_handle)(INTEGER(debug)) { GENPTR_INTEGER(debug) if (*debug) fprintf(stderr, "DB-All.e error %d: %s\n", last_err_code, last_err_msg); exit(1); } /** * Default callback that prints a message and exists, except in case of overflows. * * In case of overflows it prints a warning and continues execution */ F77_INTEGER_FUNCTION(idba_error_handle_tolerating_overflows)(INTEGER(debug)) { GENPTR_INTEGER(debug) if (last_err_code != WR_ERR_NOTFOUND) { if (*debug) fprintf(stderr, "DB-All.e error %d: %s\n", last_err_code, last_err_msg); exit(1); } return 0; } } dballe-7.7/fortran/Makefile.am0000644000175000017500000000632412653425014013251 00000000000000if DO_DBALLEF AM_CPPFLAGS = -I$(top_srcdir) $(WREPORT_CFLAGS) if FILE_OFFSET_BITS_64 AM_CPPFLAGS += -D_FILE_OFFSET_BITS=64 endif # libdballef dballeincludedir = $(includedir)/dballe # Include the F90 interface file as well dist_dballeinclude_HEADERS = dballef.h dballeff.h dist_noinst_HEADERS = handles.h lib_LTLIBRARIES = libdballef.la libdballef_la_SOURCES = \ error.cc \ trace.cc \ binding.cc libdballef_la_LIBADD = ../dballe/libdballe.la -lcnf libdballef_la_LDFLAGS = -version-info @LIBDBALLEF_VERSION_INFO@ # # Unit testing # TESTS_ENVIRONMENT = $(top_srcdir)/extra/runtest check_PROGRAMS = check_missing_msg #TESTS = $(check_PROGRAMS) dbtestlib = test.f90 dbtest.f90 CXXFLAGS += -O0 check_missing_msg_SOURCES = test.f90 check_missing_msg.f90 check_missing_msg_LDADD = ./libdballef.la -lcnf -lpopt check_missing_msg_FCFLAGS = -g check_PROGRAMS += check_real0 check_range check_fdballe check_attrs check_missing check_segfault1 check_multiplehandler check_spiegab check_messages check_real0_SOURCES = $(dbtestlib) check_real0.f90 check_real0_LDADD = ./libdballef.la -lcnf -lpopt check_real0_FCFLAGS = -g check_range_SOURCES = $(dbtestlib) check_range.f90 check_range_LDADD = ./libdballef.la -lcnf -lpopt check_range_FCFLAGS = -g check_fdballe_SOURCES = $(dbtestlib) check_fdballe.f90 check_fdballe_LDADD = ./libdballef.la -lcnf -lpopt check_fdballe_FCFLAGS = -g check_attrs_SOURCES = $(dbtestlib) check_attrs.f90 check_attrs_LDADD = ./libdballef.la -lcnf -lpopt check_attrs_FCFLAGS = -g check_missing_SOURCES = $(dbtestlib) check_missing.f90 check_missing_LDADD = ./libdballef.la -lcnf -lpopt check_missing_FCFLAGS = -g check_segfault1_SOURCES = $(dbtestlib) check_segfault1.f90 check_segfault1_LDADD = ./libdballef.la -lcnf -lpopt check_segfault1_FCFLAGS = -g check_spiegab_SOURCES = $(dbtestlib) check_spiegab.f90 check_spiegab_LDADD = ./libdballef.la -lcnf -lpopt check_spiegab_FCFLAGS = -g check_messages_SOURCES = $(dbtestlib) check_messages.f90 check_messages_LDADD = ./libdballef.la -lcnf -lpopt check_messages_FCFLAGS = -g check_messages_stdinstdout_SOURCES = $(dbtestlib) check_messages_stdinstdout.f90 check_messages_stdinstdout_LDADD = ./libdballef.la -lcnf -lpopt check_messages_stdinstdout_FCFLAGS = -g check_multiplehandler_SOURCES = $(dbtestlib) check_multiplehandler.f90 check_multiplehandler_LDADD = ./libdballef.la -lcnf -lpopt check_multiplehandler_FCFLAGS = -g noinst_PROGRAMS = dumpmsg_dballe mkmsg mkmsg-sca genattr dumpmsg_dballe_SOURCES = dumpmsg_dballe.f90 dumpmsg_dballe_LDADD = ../fortran/libdballef.la -lcnf -lpopt dumpmsg_dballe_FCFLAGS = -g mkmsg_SOURCES = mkmsg.f90 mkmsg_LDADD = ../fortran/libdballef.la -lcnf -lpopt mkmsg_FCFLAGS = -g mkmsg_sca_SOURCES = mkmsg-sca.f90 mkmsg_sca_LDADD = ../fortran/libdballef.la -lcnf -lpopt mkmsg_sca_FCFLAGS = -g genattr_SOURCES = genattr.f90 genattr_LDADD = ../fortran/libdballef.la -lcnf -lpopt genattr_FCFLAGS = -g noinst_PROGRAMS += dump_dballe check_messages_stdinstdout dump_dballe_SOURCES = dump_dballe.f90 dump_dballe_LDADD = ../fortran/libdballef.la -lcnf -lpopt dump_dballe_FCFLAGS = -g EXTRA_DIST = fortran.dox check-utils.h error.h trace.h CLEANFILES = *.mod check-local: for test in $(check_PROGRAMS); do \ $(TESTS_ENVIRONMENT) $$test ; \ done endif dballe-7.7/fortran/mkmsg-sca.f900000644000175000017500000000370312652630043013414 00000000000000 program mkmsg ! **************************** ! * Create a test message file ! **************************** integer handle, nstaz, ndata, nattr integer i, i1, i2, tmp integer id,height,codrete character fname*256,encoding*10,cname*20,rete*20,value*255 character btable*10,starbtable*10 real*8 dlat,dlon external errorrep call idba_error_set_callback(0, errorrep, 2, i) ! Open a session call getarg(1,fname) call getarg(2,encoding) call idba_messaggi(handle, fname, "w", encoding) ! Write a measured value call idba_unsetall(handle) call idba_setlevel(handle, 1, 2, 3, 4) call idba_settimerange(handle, 5, 6, 7) call idba_seti(handle,"B12101",300) call idba_prendilo(handle) ! Write a station value call idba_unsetall(handle) call idba_setcontextana(handle) call idba_setc(handle,"rep_memo","temp") call idba_seti(handle,"block",1) call idba_setc(handle,'query',"message generic") call idba_prendilo(handle) ! Done call idba_fatto(handle) call exit (0) end ! ******************** ! * Utility functions ! ******************** ! Compute the length of a string integer function istrlen(string) character string*(*) istrlen = len(string) do while ((string(istrlen:istrlen).eq." " .or. & string(istrlen:istrlen).eq."").and. & istrlen.gt.0) istrlen = istrlen - 1 enddo return end subroutine errorrep(val) integer val character buf*1000 ier = idba_error_code() if (ier.ne.0) then print *,ier," error in ",val call idba_error_message(buf) print *,buf(:istrlen(buf)) call idba_error_context(buf) print *,buf(:istrlen(buf)) call idba_error_details(buf) print *,buf(:istrlen(buf)) call exit (1) end if return end dballe-7.7/fortran/dump_dballe.f900000644000175000017500000000606112652630043014002 00000000000000 program dump_dballe ! ***************************************** ! * Dump the contents of a dballe database ! ***************************************** integer dbahandle, handle, handle_ana, nstaz, ndata, nattr integer i, i1, i2, tmp integer id,height character cname*20,rete*20,value*255,avalue*255 character btable*10,starbtable*10 real dlat,dlon external errorrep call idba_error_set_callback(0, errorrep, 2, i) ! Database login call idba_presentati(dbahandle, "test", "enrico", "") ! Open a session call idba_preparati(dbahandle, handle_ana, "read", "read", "read") call idba_preparati(dbahandle, handle, "read", "read", "read") ! Query all the stations call idba_quantesono(handle_ana, nstaz) write (*,*) nstaz," stazioni:" do i=1, nstaz call idba_elencamele(handle_ana) call idba_enqc(handle_ana, "name", cname) call idba_enqi(handle_ana, "ana_id", id) call idba_enqr(handle_ana, "lat", dlat) call idba_enqr(handle_ana, "lon", dlon) call idba_enqi(handle_ana, "height", height) call idba_enqc(handle_ana,"rep_memo",rete) write (*,*) "Staz ",id," (",dlat,",",dlon,") '", & cname(:istrlen(cname)),"' h:",height, & " ",rep_memo call idba_seti(handle,"ana_id",id) call idba_voglioquesto(handle,ndata) write (*,*) " ",ndata," dati:" do i1=1, ndata call idba_dammelo(handle,btable) call idba_enqc(handle,btable,value) write (*,*) ' var ',btable(:istrlen(btable)),": ", & value(:istrlen(btable)) call idba_enqi(handle,"!context_id",tmp) write (*,*) " CTX: ",tmp call idba_voglioancora (handle,nattr) write (*,*) " ",nattr," attributi:" do i2=1, nattr call idba_ancora(handle,starbtable) call idba_enqc(handle,starbtable,avalue) write(*,*) " attr ",starbtable(:istrlen(starbtable)), & ": ",avalue(:istrlen(avalue)) enddo enddo enddo call idba_fatto(handle_ana) call idba_fatto(handle) call idba_arrivederci(dbahandle) call exit (0) end ! ******************** ! * Utility functions ! ******************** ! Compute the length of a string integer function istrlen(string) character string*(*) istrlen = len(string) do while ((string(istrlen:istrlen).eq." " .or. & string(istrlen:istrlen).eq."").and. & istrlen.gt.0) istrlen = istrlen - 1 enddo return end subroutine errorrep(val) integer val character buf*1000 ier = idba_error_code() if (ier.ne.0) then print *,ier," error in ",val call idba_error_message(buf) print *,buf(:istrlen(buf)) call idba_error_context(buf) print *,buf(:istrlen(buf)) call idba_error_details(buf) print *,buf(:istrlen(buf)) call exit (1) end if return end dballe-7.7/fortran/error.h0000644000175000017500000000222712652630043012514 00000000000000/* * Copyright (C) 2005--2010 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef FDBA_ERROR_H #define FDBA_ERROR_H #include namespace dballe { struct DB; namespace fortran { struct API; /// Initialise error handlers void error_init(); /// Digest an exception turning it into a fortran API result code int error(wreport::error& e); /// Return a success code, updating the error information accordingly int success(); } } #endif dballe-7.7/fortran/trace.cc0000644000175000017500000001546112652630043012623 00000000000000/* * Copyright (C) 2013--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "trace.h" #include #include #include using namespace std; namespace { std::string c_escape(const std::string& str) { string res; for (string::const_iterator i = str.begin(); i != str.end(); ++i) if (*i == '\n') res += "\\n"; else if (*i == '\t') res += "\\t"; else if (*i == 0 || iscntrl(*i)) { char buf[5]; snprintf(buf, 5, "\\x%02x", (unsigned int)*i); res += buf; } else if (*i == '"' || *i == '\\') { res += "\\"; res += *i; } else res += *i; return res; } } namespace dballe { namespace fortran { bool do_trace = false; FILE* trace_file = 0; void trace_init() { // Init API tracing if requested const char* tracefile = getenv("DBALLE_TRACE_FORTRAN"); if (tracefile) { trace_file = fopen(tracefile, "at"); do_trace = true; fprintf(trace_file, "// ** Execution begins **\n"); } else { trace_file = 0; do_trace = false; } } void log_presentati_url(int handle, const char* chosen_dsn) { string arg1 = c_escape(chosen_dsn); fprintf(trace_file, "auto_ptr db%d(DB::connect_from_url(\"%s\"));\n", handle, arg1.c_str()); } void log_presentati_dsn(int handle, const char* dsn, const char* user, const char* pwd) { string arg1 = c_escape(dsn); string arg2 = c_escape(user); fprintf(trace_file, "auto_ptr db%d(DB::connect(\"%s\", \"%s\", \"xxx\"));\n", handle, arg1.c_str(), arg2.c_str()); } void log_arrivederci(int handle) { fprintf(trace_file, "// db%d not used anymore\n", handle); } void log_error(wreport::error& e) { fprintf(trace_file, "// error: %s\n", e.what()); } void log_result(int res) { fprintf(trace_file, "wassert(actual(ires) == %d);\n", res); } void log_result(const char* res) { if (res) { string arg = c_escape(res); fprintf(trace_file, "wassert(actual(sres) == \"%s\");\n", arg.c_str()); } else fprintf(trace_file, "wassert(actual(sres) == null);\n"); } void SessionTracer::log_preparati(int dbahandle, int handle, const char* anaflag, const char* dataflag, const char* attrflag) { snprintf(trace_tag, 10, "dbapi%d", handle); fprintf(trace_file, "DbAPI %s(*db%d, \"%s\", \"%s\", \"%s\");\n", trace_tag, dbahandle, anaflag, dataflag, attrflag); } void SessionTracer::log_messaggi(int handle, const char* filename, const char* mode, const char* type) { snprintf(trace_tag, 10, "msgapi%d", handle); string arg1(c_escape(filename)); fprintf(trace_file, "MsgAPI %s(\"%s\", \"%s\", %s);\n", trace_tag, arg1.c_str(), mode, type); } void SessionTracer::log_func(const char* call) { fprintf(trace_file, "%s.%s();\n", trace_tag, call); } void SessionTracer::log_quantesono() { fprintf(trace_file, "ires = %s.quantesono();\n", trace_tag); } void SessionTracer::log_voglioquesto() { fprintf(trace_file, "ires = %s.voglioquesto();\n", trace_tag); } void SessionTracer::log_voglioancora() { fprintf(trace_file, "ires = %s.voglioancora();\n", trace_tag); } void SessionTracer::log_dammelo() { fprintf(trace_file, "sres = %s.dammelo();\n", trace_tag); } void SessionTracer::log_ancora() { fprintf(trace_file, "sres = %s.ancora();\n", trace_tag); } void SessionTracer::log_set(const char* parm, int val) { string arg = c_escape(parm); fprintf(trace_file, "%s.seti(\"%s\", %d);\n", trace_tag, arg.c_str(), val); } void SessionTracer::log_set(const char* parm, double val) { string arg = c_escape(parm); fprintf(trace_file, "%s.setd(\"%s\", %f);\n", trace_tag, arg.c_str(), val); } void SessionTracer::log_set(const char* parm, const char* val) { string arg1 = c_escape(parm); string arg2 = c_escape(val); fprintf(trace_file, "%s.setc(\"%s\", \"%s\");\n", trace_tag, arg1.c_str(), arg2.c_str()); } void SessionTracer::log_setlevel(int ltype1, int l1, int ltype2, int l2) { fprintf(trace_file, "%s.setlevel(%d, %d, %d, %d);\n", trace_tag, ltype1, l1, ltype2, l2); } void SessionTracer::log_settimerange(int pind, int p1, int p2) { fprintf(trace_file, "%s.settimerange(%d, %d, %d);\n", trace_tag, pind, p1, p2); } void SessionTracer::log_setdate(int y, int m, int d, int ho, int mi, int se, const char* what) { fprintf(trace_file, "%s.setdate%s(%d, %d, %d, %d, %d, %d);\n", trace_tag, what, y, m, d, ho, mi, se); } void SessionTracer::log_unset(const char* parm) { string arg = c_escape(parm); fprintf(trace_file, "%s.unset(\"%s\");\n", trace_tag, arg.c_str()); } void SessionTracer::log_scopa(const char* fname) { if (fname) { string arg = c_escape(fname); fprintf(trace_file, "%s.scopa(\"%s\");\n", trace_tag, arg.c_str()); } else fprintf(trace_file, "%s.scopa();\n", trace_tag); } void SessionTracer::log_fatto() { fprintf(trace_file, "// %s not used anymore\n", trace_tag); } void SessionTracer::log_messages_open_input(const char* fname, const char* mode, const char* format, bool simplified) { string arg1 = c_escape(fname); string arg2 = c_escape(mode); fprintf(trace_file, "%s.messages_open_input(\"%s\", \"%s\", %s, %s);\n", trace_tag, arg1.c_str(), arg2.c_str(), format, simplified ? "true" : "false"); } void SessionTracer::log_messages_open_output(const char* fname, const char* mode, const char* format) { string arg1 = c_escape(fname); string arg2 = c_escape(mode); fprintf(trace_file, "%s.messages_open_output(\"%s\", \"%s\", %s);\n", trace_tag, arg1.c_str(), arg2.c_str(), format); } void SessionTracer::log_messages_read_next() { fprintf(trace_file, "ires = %s.messages_read_next();\n", trace_tag); } void SessionTracer::log_messages_write_next(const char* template_name) { string arg = c_escape(template_name); fprintf(trace_file, "%s.messages_write_next(\"%s\");\n", trace_tag, arg.c_str()); } } } void dballe_fortran_debug_flush_trace_log() { if (dballe::fortran::trace_file) fflush(dballe::fortran::trace_file); } dballe-7.7/fortran/dumpmsg_dballe.f900000644000175000017500000000643512652630043014516 00000000000000! Copyright (C) 2011 ARP1-SIM ! ! This program is free software; you can redistribute it and/or modify ! it under the terms of the GNU General Public License as published by ! the Free Software Foundation; either version 2 of the License. ! ! This program is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! GNU General Public License for more details. ! ! You should have received a copy of the GNU General Public License ! along with this program; if not, write to the Free Software ! Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ! ! Author: Paolo Patruno program dump_dballe ! **************************************************** ! * Dump the contents of a weather messages in a file ! **************************************************** implicit none integer :: handle, nstaz, ndata, nattr integer :: i, i1, i2, type1, l1, type2, l2 integer :: height, year, month, day, hour, minute, second character(len=255) :: fname,prettyvalue character(len=20) :: cname, rep_memo,value, avalue character(len=10) :: btable, starbtable doubleprecision ::dlat,dlon include "dballef.h" external errorrep call getarg(1,fname) call idba_error_set_callback(0, errorrep, 0, i) ! Open a session call idba_messaggi(handle, fname, "r", "BUFR") ! Query all the stations do while (.true.) call idba_quantesono(handle, nstaz) if (nstaz .eq. 0) exit call idba_elencamele(handle) call idba_enq(handle, "name", cname) call idba_enq(handle, "lat", dlat) call idba_enq(handle, "lon", dlon) call idba_enq(handle, "height", height) call idba_enq(handle,"rep_memo",rep_memo) write (*,*) "Staz: ",trim(cname)," (",dlat,",",dlon,")"," h:",height," network: ",rep_memo !call idba_set(handle,"varlist","B12101,B11002") ! only on DB is valid call idba_voglioquesto(handle,ndata) !write (*,*) " ",ndata," dati:" ! only on DB is valid do i1=1, ndata call idba_dammelo(handle,btable) if (btable /= "B12101" .and. btable /= "B11002") cycle call idba_enqdate(handle, year, month, day, hour, minute, second) call idba_enqlevel(handle, type1, l1, type2, l2) call idba_enq(handle,btable,value) print*,"----" write (*,*) "date time: ",year, month, day, hour, minute call idba_spiegal(handle,type1,l1,type2,l2,prettyvalue) write (*,*) trim(prettyvalue) call idba_spiegab(handle,btable,value,prettyvalue) write (*,*) trim(prettyvalue) call idba_voglioancora (handle,nattr) if (nattr > 0) then write (*,*) " ",nattr," attributi:" do i2=1, nattr call idba_ancora(handle,starbtable) call idba_enq(handle,starbtable,avalue) write(*,*) " attr ",trim(starbtable),": ",avalue enddo end if enddo enddo call idba_fatto(handle) call exit (0) end program dump_dballe subroutine errorrep(val) integer :: val character(len=1000) :: buf ier = idba_error_code() if (ier.ne.0) then print *,ier," error in ",val call idba_error_message(buf) print *,trim(buf) call idba_error_context(buf) print *,trim(buf) call idba_error_details(buf) print *,trim(buf) call exit (1) end if return end subroutine errorrep dballe-7.7/fortran/test.f900000644000175000017500000000171012652630043012505 00000000000000 module test contains ! Continue execution only if there was no error subroutine ensure_no_error(message) character (len=*) :: message integer :: idba_error_code, ier character (len=1000) :: buf ! print *,"siamo a ",message ier = idba_error_code() if (ier.ne.0) then print *,ier," in ",message call idba_error_message(buf) print *,trim(buf) call idba_error_context(buf) print *,trim(buf) call idba_error_details(buf) print *,trim(buf) call exit (1) end if return endsubroutine ensure_no_error ! Print an error if the given logical value is false subroutine ensure(message, value) character (len=*) :: message logical :: value if (.not.value) then print *,"Check failed in ",message call exit (1) end if return endsubroutine ensure endmodule test dballe-7.7/fortran/check_multiplehandler.f900000644000175000017500000001562412652630043016065 00000000000000 program check_fdballe ! ***************************************** ! * Test suite for DBALLE Fortran bindings ! ***************************************** use dbtest implicit none include "dballef.h" integer :: dbahandler, dbahandlew, handler, handlew,i,i1,i2,i3,i4,i5,i6,ival,saved_id real :: rval double precision :: dval character (len=10) :: param character (len=255) :: cval external :: testcb ! call fdba_error_set_callback(0, testcb, 2, i) ! Database login call dbinit(dbahandler) ! if I use different handles it do not work for sqlite !!$! Database login !!$ call dbinit(dbahandlew) dbahandlew=dbahandler ! Open a session call idba_preparati(dbahandler, handler, "read", "read", "read") call ensure_no_error("preparati read") ! Open a session call idba_preparati(dbahandlew, handlew, "write", "write", "write") call ensure_no_error("preparati write") ! Clear the database call idba_scopa(handlew, "") call ensure_no_error("scopa") ! Insert some data call idba_setd(handlew, "lat", 30D00) call ensure_no_error("setd 0") call idba_setr(handlew, "lon", 10.0) call ensure_no_error("setr 1") call idba_setc(handlew, "mobile", "0") call ensure_no_error("setc 2") call idba_seti(handlew, "year", 2006) call ensure_no_error("seti 3") call idba_seti(handlew, "month", 1) call ensure_no_error("seti 4") call idba_seti(handlew, "day", 2) call ensure_no_error("seti 5") call idba_seti(handlew, "hour", 3) call ensure_no_error("seti 6") call idba_seti(handlew, "min", 4) call ensure_no_error("seti 7") call idba_setc(handlew, "leveltype1", "1") call ensure_no_error("setc 8") call idba_seti(handlew, "l1", 1) call ensure_no_error("seti 9") call idba_setc(handlew, "leveltype2", "1") call ensure_no_error("seti 10") call idba_seti(handlew, "l2", 1) call ensure_no_error("seti 11") call idba_seti(handlew, "pindicator", 20) call ensure_no_error("seti 12") call idba_seti(handlew, "p1", 1) call ensure_no_error("seti 13") call idba_seti(handlew, "p2", 1) call ensure_no_error("seti 14") call idba_setc(handlew, "rep_memo", "synop") call ensure_no_error("seti 15") call idba_setc(handlew, "B01011", "DB-All.e!") call ensure_no_error("setc 16") ! Perform the insert call idba_prendilo(handlew) call ensure_no_error("first prendilo") ! Query back the data ! call idba_ricominciamo(handle) call idba_unsetall(handler) call ensure_no_error("ricominciamo") call idba_setr(handler, "latmin", 20.0) call ensure_no_error("query setf 0") call idba_setr(handler, "latmax", 50.0) call ensure_no_error("query setf 1") call idba_setr(handler, "lonmin", 5.0) call ensure_no_error("query setf 2") call idba_setr(handler, "lonmax", 20.0) call ensure_no_error("query setf 3") call idba_voglioquesto(handler, i) call ensure_no_error("voglioquesto") call ensure("voglioquesto result", i.eq.1) ! Read the results of the query ! TODO: make a for loop instead do while (i.gt.0) call idba_dammelo(handler, param) call ensure_no_error("dammelo") call idba_enqc(handler, param, cval) call ensure_no_error("dammelo enqc 0") call idba_enqi(handler, "year", ival) call ensure_no_error("dammelo enqi 1") call idba_enqr(handler, "lat", rval) call ensure_no_error("dammelo enqr 2") call idba_enqd(handler, "lon", dval) call ensure_no_error("dammelo enqd 3") call idba_enqc(handler, "lon", cval) call ensure_no_error("dammelo enqc 4") call idba_enqdate(handler, i1, i2, i3, i4, i5, i6) call ensure_no_error("dammelo enqdate") call ensure("enqdate i1", i1.eq.2006) call ensure("enqdate i2", i2.eq.1) call ensure("enqdate i3", i3.eq.2) call ensure("enqdate i4", i4.eq.3) call ensure("enqdate i5", i5.eq.4) call ensure("enqdate i6", i6.eq.0) call idba_enqlevel(handler, i1, i2, i3, i4) call ensure_no_error("dammelo enqlevel") call ensure("enqlevel i1", i1.eq.1) call ensure("enqlevel i2", i2.eq.1) call ensure("enqlevel i3", i3.eq.1) call ensure("enqlevel i4", i4.eq.1) call idba_enqtimerange(handler, i1, i2, i3) call ensure_no_error("dammelo enqtimerange") call ensure("enqdate i1", i1.eq.20) call ensure("enqdate i2", i2.eq.1) call ensure("enqdate i3", i3.eq.1) i = i - 1 ! Insert some data call idba_setd(handlew, "lat", 30D00) call ensure_no_error("setd 0") call idba_setr(handlew, "lon", 10.0) call ensure_no_error("setr 1") call idba_setc(handlew, "mobile", "0") call ensure_no_error("setc 2") call idba_seti(handlew, "year", 2007) call ensure_no_error("seti 3") call idba_seti(handlew, "month", 1) call ensure_no_error("seti 4") call idba_seti(handlew, "day", 2) call ensure_no_error("seti 5") call idba_seti(handlew, "hour", 3) call ensure_no_error("seti 6") call idba_seti(handlew, "min", 4) call ensure_no_error("seti 7") call idba_setc(handlew, "leveltype1", "1") call ensure_no_error("setc 8") call idba_seti(handlew, "l1", 1) call ensure_no_error("seti 9") call idba_setc(handlew, "leveltype2", "1") call ensure_no_error("seti 10") call idba_seti(handlew, "l2", 1) call ensure_no_error("seti 11") call idba_seti(handlew, "pindicator", 20) call ensure_no_error("seti 12") call idba_seti(handlew, "p1", 1) call ensure_no_error("seti 13") call idba_seti(handlew, "p2", 1) call ensure_no_error("seti 14") call idba_setc(handlew, "rep_memo", "synop") call ensure_no_error("seti 15") call idba_setc(handlew, "B01011", "DB-All.e!") call ensure_no_error("setc 16") ! Perform the insert call idba_prendilo(handlew) call ensure_no_error("first prendilo") enddo call idba_fatto(handlew) call ensure_no_error("fatto") call idba_fatto(handler) call ensure_no_error("fatto") ! use only in multiple dbhandlers case !!$ call idba_arrivederci(dbahandlew) !!$ call ensure_no_error("arrivederci w") call idba_arrivederci(dbahandler) call ensure_no_error("arrivederci r") ! If we made it so far, exit with no error print*,"check_fdballe: all tests succeed." call exit (0) end program include "check-utils.h" dballe-7.7/fortran/check_range.f900000644000175000017500000000270712652630043013766 00000000000000program check_range ! ***************************************** ! * Test suite for DBALLE Fortran bindings ! ***************************************** use dbtest include "dballef.h" integer :: handle,idbhandle,handle_err, errcode real :: rval !data var/ "B22070", "B22074", "B22001", "B22071", "B22042"/ integer debug data debug/1/ !call idba_error_set_callback(0,idba_default_error_handler,debug,handle_err) ! Database login call dbinit(idbhandle) ! Open a session call idba_preparati(idbhandle,handle,"write","write","write") call ensure_no_error("preparati") ! Check that NaN values are trapped rval = 0. rval = log(rval) / log(rval) call idba_set(handle, "B12103", log(rval)) errcode = idba_error_code() call ensure("set to NaN", errcode == 13) ! Check that negative reals can be read call idba_set(handle, "lon", -12.3456) call ensure_no_error("set lon negative") call idba_test_input_to_output(handle) call ensure_no_error("input to output") call idba_enqr(handle, "lon", rval) call ensure_no_error("enq lon negative") call ensure("read negative real", rval == -12.3456) call idba_fatto(handle) call ensure_no_error("fatto") call idba_arrivederci(idbhandle) call ensure_no_error("arrivederci") call exit (0) end program check_range include "check-utils.h" dballe-7.7/fortran/check_missing_msg.f900000644000175000017500000001062312652630043015205 00000000000000 program check_missing ! ***************************************** ! * Test suite for DBALLE Fortran bindings ! ***************************************** use test include "dballef.h" integer handle, ival, ndata, n, i integer (kind=dba_int_b):: bval real rval real*8 dval character cval*255, btable*8 character(len=1024) :: fname external testcb ! call fdba_error_set_callback(0, testcb, 2, i) call getenv('DBA_TESTDATA', fname) fname = trim(fname) // "/bufr/temp-bad5.bufr" ! Open a session call idba_messaggi(handle, fname, "r", "BUFR") call ensure_no_error("messaggi") ! Try reading 'missing' values call idba_enqb(handle, "latmin", bval) call ensure_no_error("enq key byte") call ensure("enq empty key byte", bval.eq.DBA_MVB) call idba_enqc(handle, "latmin", cval) call ensure_no_error("enq key char") call ensure("enq empty key char", cval.eq.DBA_MVC) call idba_enqi(handle, "latmin", ival) call ensure_no_error("enq key int") call ensure("enq empty key int", ival.eq.DBA_MVI) call idba_enqr(handle, "latmin", rval) call ensure_no_error("enq key real") call ensure("enq empty key real", rval.eq.DBA_MVR) call idba_enqd(handle, "latmin", dval) call ensure_no_error("enq key double") call ensure("enq empty key double", dval.eq.DBA_MVD) call idba_enq(handle, "latmin", dval) call ensure_no_error("enq key auto double") call ensure("enq empty key auto double", dval.eq.DBA_MVD) call idba_enqb(handle, "B05002", bval) call ensure_no_error("enq var byte") call ensure("enq empty var byte", bval.eq.DBA_MVB) call idba_enqc(handle, "B05002", cval) call ensure_no_error("enq var char") call ensure("enq empty var char", cval.eq.DBA_MVC) call idba_enqi(handle, "B05002", ival) call ensure_no_error("enq var int") call ensure("enq empty var int", ival.eq.DBA_MVI) call idba_enqr(handle, "B05002", rval) call ensure_no_error("enq var real") call ensure("enq empty var real", rval.eq.DBA_MVR) call idba_enqd(handle, "B05002", dval) call ensure_no_error("enq var double") call ensure("enq empty var double", dval.eq.DBA_MVD) call idba_enq(handle, "B05002", dval) call ensure_no_error("enq var auto double") call ensure("enq empty var auto double", dval.eq.DBA_MVD) ! Try using the 'missing' values call idba_setb(handle, "lat", DBA_MVB) call ensure_no_error("unset key byte") call idba_setc(handle, "lat", DBA_MVC) call ensure_no_error("unset key char") call idba_seti(handle, "lat", DBA_MVI) call ensure_no_error("unset key int") call idba_setr(handle, "lat", DBA_MVR) call ensure_no_error("unset key real") call idba_setd(handle, "lat", DBA_MVD) call ensure_no_error("unset key double") call idba_setb(handle, "B12001", DBA_MVB) call ensure_no_error("unset var byte") call idba_setc(handle, "B12001", DBA_MVC) call ensure_no_error("unset var char") call idba_seti(handle, "B12001", DBA_MVI) call ensure_no_error("unset var int") call idba_setr(handle, "B12001", DBA_MVR) call ensure_no_error("unset var real") call idba_setd(handle, "B12001", DBA_MVD) call ensure_no_error("unset var double") call idba_unsetall(handle) call ensure_no_error("unsetall") n = 1 do while ( n > 0 ) call idba_voglioquesto (handle,n) call ensure_no_error("voglioquesto") if (n == DBA_MVI) then exit end if do i = 1, n call idba_dammelo (handle,btable) call ensure_no_error("dammelo") call idba_enqd (handle,"B11001",dval) call ensure_no_error("enqd from msg") call idba_enqr (handle,"B11001",rval) call ensure_no_error("enqr from msg") call idba_enqi (handle,"B11001",ival) call ensure_no_error("enqi from msg") ! Value does not fit in a byte !call idba_enqb (handle,"B11001",bval) !call ensure_no_error("enqb from msg") end do end do call idba_fatto(handle) call ensure_no_error("fatto") ! If we made it so far, exit with no error print*,"check_missing: all tests succeed." call exit (0) end program include "check-utils.h" dballe-7.7/fortran/check_real0.f900000644000175000017500000000341712652630043013674 00000000000000 program check_real0 ! ***************************************** ! * Test suite for DBALLE Fortran bindings ! ***************************************** use dbtest include "dballef.h" integer :: handle,idbhandle,handle_err !data var/ "B22070", "B22074", "B22001", "B22071", "B22042"/ !integer debug !data debug/1/ !call idba_error_set_callback(0,idba_default_error_handler,debug,handle_err) ! Database login call dbinit(idbhandle) ! Open a session call idba_preparati(idbhandle,handle,"write","write","write") call ensure_no_error("preparati") ! Clear the database call idba_scopa(handle, "") call ensure_no_error("scopa") ! Insert some data with a 0.0D0 value call idba_unsetall (handle) call idba_set (handle,"lat",44.2) call ensure_no_error("set lat") call idba_set (handle,"lon",11.5) call ensure_no_error("set lon") call idba_set (handle,"mobile",0) call ensure_no_error("set mobile") call idba_set (handle,"rep_memo","synop") call ensure_no_error("set rep_memo") call idba_setlevel (handle,1,0,0,0) call ensure_no_error("set level") call idba_settimerange (handle,0,0,0) call ensure_no_error("set timerange") call idba_setdate (handle,2007,12,11,12,30,00) call ensure_no_error("set date") call idba_set(handle,"B22070",0.0D0) call ensure_no_error("set B22070 to 0.0D0") call idba_prendilo (handle) call ensure_no_error("prendilo") call idba_fatto(handle) call ensure_no_error("fatto") call idba_arrivederci(idbhandle) call ensure_no_error("arrivederci") call exit (0) end program check_real0 include "check-utils.h" dballe-7.7/fortran/check_attrs.f900000644000175000017500000000744712652630043014035 00000000000000 program check_attrs use dbtest include "dballef.h" ! ***************************************** ! * Dump the contents of a dballe database ! ***************************************** integer dbahandle, handle, handleinit, nstaz, ndata, nattr integer i, i1, i2, tmp integer id,height,codrete character cname*20,rete*20,value*255,avalue*255 character btable*10,starbtable*10 real dlat,dlon external errorrep ! call idba_error_set_callback(0, errorrep, 2, i) ! Database login call dbinit(dbahandle) ! Open a session call idba_preparati(dbahandle, handle, "read", "read", "read") call ensure_no_error("preparati handle") call idba_preparati(dbahandle, handleinit, & "write", "write", "write") call ensure_no_error("preparati handleinit") call idba_scopa(handleinit, DBA_MVC) call ensure_no_error("scopa") ! Insert test data call idba_setd(handleinit, "lat", 12.345D00) call ensure_no_error("init 1") call idba_setd(handleinit, "lon", 12.345D00) call ensure_no_error("init 2") call idba_setlevel(handleinit, 1, 0, 0, 0) call ensure_no_error("init 3") call idba_settimerange(handleinit, 0, 0, 0) call ensure_no_error("init 4") call idba_setdate(handleinit, 2007, 06, 13, 0, 0, 0) call ensure_no_error("init 5") call idba_setd(handleinit, "B12101", 12.345D0) call ensure_no_error("init 6") call idba_setd(handleinit, "B12103", 23.456D0) call ensure_no_error("init 6") call idba_setc(handleinit, "rep_memo", 'synop') call ensure_no_error("init 6b") call idba_prendilo(handleinit) call ensure_no_error("prendilo") call idba_setr(handleinit, "*B33007", 75.0) call ensure_no_error("init 8") call idba_setc(handleinit, "*var_related", "B12101") call ensure_no_error("init 9") call idba_critica(handleinit) call ensure_no_error("critica 1") call idba_setr(handleinit, "*B33040", 80.0) call ensure_no_error("init 11") call idba_setc(handleinit, "*var_related", "B12101") call ensure_no_error("init 12") call idba_critica(handleinit) call ensure_no_error("critica 2") call idba_setr(handleinit, "*B33036", 90.0) call ensure_no_error("init 14") call idba_setc(handleinit, "*var_related", "B12101") call ensure_no_error("init 15") call idba_critica(handleinit) call ensure_no_error("critica 3") call idba_setc(handle, "var", "B12101") call ensure_no_error("query set 1") call idba_voglioquesto(handle, nattr) call ensure("I need 1 var in output", nattr.eq.1) call ensure_no_error("query voglioquesto 1") call idba_dammelo(handle, btable) call ensure_no_error("query dammelo 1") call ensure_no_error("query set 2") call idba_voglioancora(handle, nattr) call ensure_no_error("query voglioancora 1") call ensure("I need 3 values", nattr.eq.3) call idba_setc(handle, "*var", "*B33040") call ensure_no_error("query set 3") call idba_voglioancora(handle, nattr) call ensure_no_error("query voglioancora 2") call ensure("I need 1 values", nattr.eq.1) call idba_unset(handle, "*var") call ensure_no_error("query set 4") call idba_setc(handle, "*varlist", "*B33007,*B33036") call ensure_no_error("query set 5") call idba_voglioancora(handle, nattr) call ensure_no_error("query voglioancora 3") call ensure("I need 2 values", nattr.eq.2) call idba_fatto(handleinit) call idba_fatto(handle) call idba_arrivederci(dbahandle) ! If we made it so far, exit with no error print*,"check_attrs: all tests succeed." call exit (0) end include "check-utils.h" dballe-7.7/fortran/check_missing.f900000644000175000017500000000643512652630043014345 00000000000000 program check_missing ! ***************************************** ! * Test suite for DBALLE Fortran bindings ! ***************************************** use dbtest include "dballef.h" integer dbahandle, handle, ival integer (kind=dba_int_b):: bval real rval real*8 dval character cval*255 external testcb ! call fdba_error_set_callback(0, testcb, 2, i) ! Database login call dbinit(dbahandle) ! Open a session call idba_preparati(dbahandle, handle, "write", "write", "write") call ensure_no_error("preparati") ! Try reading 'missing' values call idba_enqb(handle, "lat", bval) call ensure_no_error("enq key byte") call ensure("enq empty key byte", bval.eq.DBA_MVB) call idba_enqc(handle, "lat", cval) call ensure_no_error("enq key char") call ensure("enq empty key char", cval.eq.DBA_MVC) call idba_enqi(handle, "lat", ival) call ensure_no_error("enq key int") call ensure("enq empty key int", ival.eq.DBA_MVI) call idba_enqr(handle, "lat", rval) call ensure_no_error("enq key real") call ensure("enq empty key real", rval.eq.DBA_MVR) call idba_enqd(handle, "lat", dval) call ensure_no_error("enq key double") call ensure("enq empty key double", dval.eq.DBA_MVD) call idba_enqb(handle, "B12001", bval) call ensure_no_error("enq var byte") call ensure("enq empty var byte", bval.eq.DBA_MVB) call idba_enqc(handle, "B12001", cval) call ensure_no_error("enq var char") call ensure("enq empty var char", cval.eq.DBA_MVC) call idba_enqi(handle, "B12001", ival) call ensure_no_error("enq var int") call ensure("enq empty var int", ival.eq.DBA_MVI) call idba_enqr(handle, "B12001", rval) call ensure_no_error("enq var real") call ensure("enq empty var real", rval.eq.DBA_MVR) call idba_enqd(handle, "B12001", dval) call ensure_no_error("enq var double") call ensure("enq empty var double", dval.eq.DBA_MVD) ! Try using the 'missing' values call idba_setb(handle, "lat", DBA_MVB) call ensure_no_error("unset key byte") call idba_setc(handle, "lat", DBA_MVC) call ensure_no_error("unset key char") call idba_seti(handle, "lat", DBA_MVI) call ensure_no_error("unset key int") call idba_setr(handle, "lat", DBA_MVR) call ensure_no_error("unset key real") call idba_setd(handle, "lat", DBA_MVD) call ensure_no_error("unset key double") call idba_setb(handle, "B12001", DBA_MVB) call ensure_no_error("unset var byte") call idba_setc(handle, "B12001", DBA_MVC) call ensure_no_error("unset var char") call idba_seti(handle, "B12001", DBA_MVI) call ensure_no_error("unset var int") call idba_setr(handle, "B12001", DBA_MVR) call ensure_no_error("unset var real") call idba_setd(handle, "B12001", DBA_MVD) call ensure_no_error("unset var double") call idba_fatto(handle) call ensure_no_error("fatto") call idba_arrivederci(dbahandle) call ensure_no_error("arrivederci") ! If we made it so far, exit with no error print*,"check_missing: all tests succeed." call exit (0) end program include "check-utils.h" dballe-7.7/fortran/check_messages.f900000644000175000017500000001102212652630043014467 00000000000000 program check_fdballe ! ***************************************** ! * Test suite for DBALLE Fortran bindings ! ***************************************** use dbtest include "dballeff.h" integer :: dbahandle, handle,i,i1,i2,i3,i4,i5,i6,ival,saved_id real :: rval double precision :: dval character (len=10) :: param character (len=255) :: cval character (len=512) :: infile external :: testcb logical :: status ! call fdba_error_set_callback(0, testcb, 2, i) ier = idba_presentati(dbahandle, "mem:", char(0), char(0)) call ensure_no_error("presentati") ier = idba_preparati(dbahandle, handle, "write", "write", "write") call ensure_no_error("preparati") call getenv("DBA_TESTDATA", infile) infile = trim(infile) // "/bufr/db-messages1.bufr"; ! Database login ier = idba_messages_open_input(handle, infile, "rb", "BUFR", .true.) call ensure_no_error("messages_open_input") ! Open a session ier = idba_unsetall(handle) call ensure_no_error("unsetall") ! Query the first message/subset ier = idba_remove_all(handle) ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 1") call ensure("messages_read_next result 1", status) ier = idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto msg1") call ensure("voglioquesto result msg1", i.eq.88) ! Querying again gives the same data ier = idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto msg1 dup") call ensure("voglioquesto result msg1", i.eq.88) ! Advance to the next message ier = idba_remove_all(handle) ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 2") call ensure("messages_read_next result 2", status) ier = idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto 2") call ensure("voglioquesto result msg2", i.eq.9) ! And the other messages ier = idba_remove_all(handle) ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 3") call ensure("messages_read_next result 3", status) ier = idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto 3") call ensure("voglioquesto result msg3", i.eq.193) ier = idba_remove_all(handle) ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 4") call ensure("messages_read_next result 4", status) ier = idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto 4") call ensure("voglioquesto result msg4", i.eq.182) ier = idba_remove_all(handle) ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 5") call ensure("messages_read_next result 5", status) ier = idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto 5") call ensure("voglioquesto result msg5", i.eq.170) ier = idba_remove_all(handle) ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 6") call ensure("messages_read_next result 6", status) ier = idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto 6") call ensure("voglioquesto result msg6", i.eq.184) ier = idba_remove_all(handle) ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 7") call ensure("messages_read_next result 7", status) ier = idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto 7") call ensure("voglioquesto result msg7", i.eq.256) ier = idba_remove_all(handle) ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 8") call ensure("messages_read_next result 8", status) ier = idba_voglioquesto(handle, i) call ensure_no_error("voglioquesto 8") call ensure("voglioquesto result msg8", i.eq.213) ier = idba_remove_all(handle) ier = idba_messages_read_next(handle, status) call ensure_no_error("messages_read_next 9") call ensure("messages_read_next result 9", .not. status ) ier = idba_fatto(handle) call ensure_no_error("fatto") ier = idba_arrivederci(dbahandle) call ensure_no_error("arrivederci") ! If we made it so far, exit with no error print*,"check_messages: all tests succeed." call exit (0) end program include "check-utils.h" dballe-7.7/fortran/dbtest.f900000644000175000017500000000113412652630043013013 00000000000000 module dbtest use test contains subroutine dbinit(dbahandle) integer::dbahandle, handle character (len=160) :: dsn,testname call getenv("DBA_DB", dsn) call getarg(0, testname) if (dsn=="") then dsn = "test:" end if call idba_presentati(dbahandle, dsn, char(0), char(0)) call ensure_no_error("presentati") call idba_preparati(dbahandle, handle, "write", "write", "write") call idba_scopa(handle, char(0)) call idba_fatto(handle) endsubroutine dbinit endmodule dbtest dballe-7.7/fortran/trace.h0000644000175000017500000000471412652630043012464 00000000000000/* * Copyright (C) 2013--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include #ifndef FDBA_TRACE_H #define FDBA_TRACE_H #define IF_TRACING(code) do { if (dballe::fortran::do_trace) { code; } } while(0) namespace dballe { namespace fortran { extern bool do_trace; void trace_init(); void log_presentati_url(int handle, const char* chosen_dsn); void log_presentati_dsn(int handle, const char* dsn, const char* user, const char* pwd); void log_arrivederci(int handle); void log_error(wreport::error& e); void log_result(int res); void log_result(const char* res); struct SessionTracer { char trace_tag[10]; void log_preparati(int dbahandle, int handle, const char* anaflag, const char* dataflag, const char* attrflag); void log_messaggi(int handle, const char* filename, const char* mode, const char* type); void log_func(const char* call); void log_quantesono(); void log_voglioquesto(); void log_voglioancora(); void log_dammelo(); void log_ancora(); void log_set(const char* parm, int val); void log_set(const char* parm, double val); void log_set(const char* parm, const char* val); void log_setlevel(int ltype1, int l1, int ltype2, int l2); void log_settimerange(int pind, int p1, int p2); void log_setdate(int y, int m, int d, int ho, int mi, int se, const char* what=""); void log_unset(const char* parm); void log_scopa(const char* fname=0); void log_fatto(); void log_messages_open_input(const char* fname, const char* mode, const char* format, bool simplified=true); void log_messages_open_output(const char* fname, const char* mode, const char* format); void log_messages_read_next(); void log_messages_write_next(const char* template_name); }; } } #endif dballe-7.7/fortran/binding.cc0000644000175000017500000014457612652630043013151 00000000000000/* * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "config.h" #include "dballe/core/verbose.h" #include "dballe/simple/msgapi.h" #include "dballe/simple/dbapi.h" #include "dballe/db/db.h" #include // memset #include #include #include "handles.h" #include "error.h" #include "trace.h" extern "C" { #include } //#define TRACEMISSING(type) fprintf(stderr, "SET TO MISSING (" type ")\n") #define TRACEMISSING(type) do {} while(0) /* * First attempt using constants */ //#define MISSING_STRING "" // Largest signed one byte value #define MISSING_BYTE SCHAR_MAX // integer 2 byte 32767 // Largest signed int value #define MISSING_INT INT_MAX //#define MISSING_REAL (3.4028235E+38f) // Largest positive float value #define MISSING_REAL FLT_MAX // Largest positive double value #define MISSING_DOUBLE DBL_MAX //#define MISSING_DOUBLE (1.79769E+308) //#define MISSING_DOUBLE (1.7976931348623167E+308) //#define MISSING_DOUBLE (1.797693134862316E+308) //#define MISSING_DOUBLE (1.79769313486E+308) //#define MISSING_DOUBLE ((double)0x7FEFFFFFFFFFFFFF) using namespace dballe; using namespace wreport; static inline void tofortran(int& val) { if (val == fortran::API::missing_int) val = MISSING_INT; } static inline int fromfortran(int val) { return val == MISSING_INT ? fortran::API::missing_int : val; } /** @defgroup fortransimple Simplified interface for Dballe * @ingroup fortran * * This module provides a simplified fortran API to Dballe. The interface is * simplified by providing functions with fewer parameters than their * counterparts in the full interface, and the omitted parameters are replaced * by useful defaults. * * The resulting interface is optimized for the common usage, making it faster * and less error prone. However, when creating complicated code with more * parallel reads and writes, it may be useful to use the functions in * ::fortranfull instead, because all parameters are explicit and their precise * semantics is always evident. * * This is a sample code for a query session with the simplified interface: * \code * call idba_presentati(dba, "myDSN", "mariorossi", "CippoLippo") * call idba_preparati(dba, handle, "read", "read", "read") * call idba_setr(handle, "latmin", 30.) * call idba_setr(handle, "latmax", 50.) * call idba_setr(handle, "lonmin", 10.) * call idba_setr(handle, "lonmax", 20.) * call idba_voglioquesto(handle, count) * do i=1,count * call idba_dammelo(handle, param) * call idba_enqd(handle, param, ...) * call idba_enqi(handle, ...) * call idba_enqr(handle, ...) * call idba_enqd(handle, ...) * call idba_enqc(handle, ...) * call idba_voglioancora(handle, countancora) * do ii=1,count * call idba_ancora(handle, param) * call idba_enqi(handle, param) * enddo * enddo * call idba_fatto(handle) * call idba_arrivederci(dba) * \endcode * * This is a sample code for a data insert session with the simplified interface: * \code * call idba_presentati(dba, "myDSN", "mariorossi", "CippoLippo") * call idba_preparati(dba, handle, "read", "add", "write") * call idba_scopa(handle, "") * call idba_setr(handle, "lat", 30.) * call idba_setr(handle, "lon", 10.) * call idba_seti(handle, .....) * call idba_seti(handle, "B12011", 5) * call idba_seti(handle, "B12012", 10) * call idba_prendilo(handle) * call idba_setc(handle, "*var", "B12012") * call idba_seti(handle, "*B33101", 50) * call idba_seti(handle, "*B33102", 75) * call idba_critica(handle) * call idba_setc(handle, "*var", "B12011") * call idba_seti(handle, "*B33101", 50) * call idba_seti(handle, "*B33102", 75) * call idba_critica(handle) * call idba_fatto(handle) * call idba_arrivederci(dba) * \endcode */ /** @file * @ingroup fortransimple * Simplified interface for Dballe. * * Every function returns an error indicator, which is 0 if no error happened, * or 1 if there has been an error. * * When an error happens, the functions in fdba_error.c can be used * to get detailed informations about it. * * \par Internals of the simplified interface * * Behind the handle returned by idba_preparati() there are a set of variables * that are used as implicit parameters: * * \li \c query ::dba_record, used to set the parameters of the query made by idba_voglioquesto() * \li \c work ::dba_record, used by idba_dammelo() to return the parameters * \li \c qc ::dba_record, used to manipulate qc data. Every time the \ref idba_enq or \ref idba_set functions are used with a variable name starting with an asterisk, they will manipulate the \c qc record instead of the others. * \li \c ana ::dba_cursor, used to iterate on the results of idba_quantesono() * \li \c query ::dba_cursor, used to iterate on the results of idba_voglioquesto() * * The simplified interface has two possible states: \c QUERY and \c RESULT. * Then the interface is in the \c QUERY state, the \ref idba_enq and \ref * idba_set functions operate in the \c query ::dba_record, to set and check the * parameters of a query. idba_voglioquesto() reads the parameters from the \c * query ::dba_record and switches the state to \c RESULT, and further calls to * idba_dammelo() will put the query results in the \c work ::dba_record, to be read by * the \ref idba_enq functions. * * In the \c RESULT state, the \ref idba_enq and \ref idba_set functions * operate on the \c work ::dba_record, to inspect the results of the queries. A * call to idba_ricominciamo() terminates the current query and goes back to * the \c QUERY state, resetting the contents of all the ::dba_record of the interface. * * idba_prendilo() inserts in the database the data coming from the \c * QUERY ::dba_record if invoked in the \c query state, or the data coming from the * \c RESULT ::dba_record if invoked in the \c result state. This is done * because inserting new values in the database should be independent from the * state. * * \ref qc functions instead always operate on the \c qc ::dba_record, which is * accessed with the \ref idba_enq and \ref idba_set functions by prefixing the * parameter name with an asterisk. */ /* Handles to give to Fortran */ #define MAX_SIMPLE 50 #define MAX_SESSION 10 using namespace std; struct HSession : public fortran::HBase { DB* db; void start() { fortran::HBase::start(); db = 0; } void stop() { if (db) delete db; fortran::HBase::stop(); } }; struct fortran::Handler hsess; struct HSimple : public fortran::HBase { fortran::API* api; fortran::SessionTracer trace; void start() { fortran::HBase::start(); api = 0; } void stop() { if (api) delete api; fortran::HBase::stop(); } }; struct fortran::Handler hsimp; // FDBA_HANDLE_BODY(simple, MAX_SIMPLE, "Dballe simple sessions") // FDBA_HANDLE_BODY(session, MAX_SESSION, "Dballe sessions") //#define STATE (simples.get(*handle)) //#define SESSION (sessions.get(simples.get(*handle).session)) //FDBA_HANDLE(session, FDBA_HANDLE(simple, *handle).session).session) static int usage_refcount = 0; static void lib_init() { if (usage_refcount > 0) return; dba_verbose_init(); fortran::trace_init(); fortran::error_init(); hsess.init("DB-All.e database sessions", "MAX_CALLBACKS"); hsimp.init("DB-All.e work sessions", "MAX_SIMPLE"); ++usage_refcount; } extern "C" { /** * Start working with a DBALLE database. * * This function can be called more than once once to connect to different * databases at the same time. * * @param dsn * The ODBC DSN of the database to use * @param user * The username used to connect to the database * @param password * The username used to connect to the database * @retval dbahandle * The database handle that can be passed to idba_preparati to work with the * database. * @return * The error indication for the function. */ F77_INTEGER_FUNCTION(idba_presentati)( INTEGER(dbahandle), CHARACTER(dsn), CHARACTER(user), CHARACTER(password) TRAIL(dsn) TRAIL(user) TRAIL(password)) { GENPTR_INTEGER(dbahandle) GENPTR_CHARACTER(dsn) GENPTR_CHARACTER(user) GENPTR_CHARACTER(password) const char* chosen_dsn; char s_dsn[256]; char s_user[20]; char s_password[20]; try { /* Import input string parameters */ cnfImpn(dsn, dsn_length, 255, s_dsn); s_dsn[255] = 0; cnfImpn(user, user_length, 19, s_user); s_user[19] = 0; cnfImpn(password, password_length, 19, s_password); s_password[19] = 0; /* Initialize the library if needed */ lib_init(); /* Allocate and initialize a new handle */ *dbahandle = hsess.request(); HSession& hs = hsess.get(*dbahandle); /* Open the DBALLE session */ /* If dsn is missing, look in the environment */ if (s_dsn[0] == 0) { chosen_dsn = getenv("DBA_DB"); if (chosen_dsn == NULL) chosen_dsn = ""; } else chosen_dsn = s_dsn; /* If dsn looks like a url, treat it accordingly */ if (DB::is_url(chosen_dsn)) { IF_TRACING(fortran::log_presentati_url(*dbahandle, chosen_dsn)); hs.db = DB::connect_from_url(chosen_dsn).release(); } else { IF_TRACING(fortran::log_presentati_dsn(*dbahandle, chosen_dsn, s_user, s_password)); hs.db = DB::connect(chosen_dsn, s_user, s_password).release(); } /* Open the database session */ return fortran::success(); } catch (error& e) { hsess.release(*dbahandle); return fortran::error(e); } } /** * Stop working with a DBALLE database * * @param dbahandle * The database handle to close. */ F77_SUBROUTINE(idba_arrivederci)(INTEGER(dbahandle)) { GENPTR_INTEGER(dbahandle) IF_TRACING(fortran::log_arrivederci(*dbahandle)); // try { hsess.release(*dbahandle); /* dba_shutdown does not exist anymore, but I keep this code commented out here as a placeholder if in the future we'll need to hook actions when the usage refcount goes to 0 if (--usage_refcount == 0) dba_shutdown(); */ // return fortran::success(); // } catch (error& e) { // return fortran::error(e); // } } /** * Starts a session with dballe. * * You can call idba_preparati() many times and get more handles. This allows * to perform many operations on the database at the same time. * * idba_preparati() has three extra parameters that can be used to limit * write operations on the database, as a limited protection against * programming errors. * * Note that some combinations of parameters are illegal, such as anaflag=read * and dataflag=add (when adding a new data, it's sometimes necessary to insert * new pseudoana records), or dataflag=rewrite and qcflag=read (when deleting * data, their attributes are deleted as well). * * @param dbahandle * The main DB-ALLe connection handle * @retval handle * The session handle returned by the function * @param anaflag * Controls access to pseudoana records and can have these values: * \li \c "read" pseudoana records cannot be inserted. * \li \c "write" it is possible to insert and delete pseudoana records. * @param dataflag * Controls access to observed data and can have these values: * \li \c "read" data cannot be modified in any way. * \li \c "add" data can be added to the database, but existing data cannot be * modified. Deletions are disabled. This is used to insert new data in the * database while preserving the data that was already present in it. * \li \c "write" data can freely be added, overwritten and deleted. * @param qcflag * Controls access to data attributes and can have these values: * \li \c "read" attributes cannot be modified in any way. * \li \c "write" attributes can freely be added, overwritten and deleted. * @return * The error indication for the function. */ F77_INTEGER_FUNCTION(idba_preparati)( INTEGER(dbahandle), INTEGER(handle), CHARACTER(anaflag), CHARACTER(dataflag), CHARACTER(attrflag) TRAIL(anaflag) TRAIL(dataflag) TRAIL(attrflag)) { GENPTR_INTEGER(dbahandle) GENPTR_INTEGER(handle) GENPTR_CHARACTER(anaflag) GENPTR_CHARACTER(dataflag) GENPTR_CHARACTER(attrflag) char c_anaflag[10]; char c_dataflag[10]; char c_attrflag[10]; cnfImpn(anaflag, anaflag_length, 10, c_anaflag); cnfImpn(dataflag, dataflag_length, 10, c_dataflag); cnfImpn(attrflag, attrflag_length, 10, c_attrflag); try { /* Check here to warn users of the introduction of idba_presentati */ /* if (session == NULL) return dba_error_consistency("idba_presentati should be called before idba_preparati"); */ /* Allocate and initialize a new handle */ *handle = hsimp.request(); HSession& hs = hsess.get(*dbahandle); HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_preparati(*dbahandle, *handle, c_anaflag, c_dataflag, c_attrflag)); h.api = new fortran::DbAPI(*hs.db, c_anaflag, c_dataflag, c_attrflag); return fortran::success(); } catch (error& e) { hsimp.release(*handle); return fortran::error(e); } } /** * Access a file with weather messages * * @retval handle * The session handle returned by the function * @param filename * Name of the file to open * @param mode * File open mode. It can be: * \li \c r for read * \li \c w for write (the old file is deleted) * \li \c a for append * @param type * Format of the data in the file. It can be: * \li \c "BUFR" * \li \c "CREX" * \li \c "AOF" (read only) * \li \c "AUTO" (autodetect, read only) * @param force_report * if 0, nothing happens; otherwise, choose the output message template * using this report type instead of the one in the message * @return * The error indication for the function. */ F77_INTEGER_FUNCTION(idba_messaggi)( INTEGER(handle), CHARACTER(filename), CHARACTER(mode), CHARACTER(type) TRAIL(filename) TRAIL(mode) TRAIL(type)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(filename) GENPTR_CHARACTER(mode) GENPTR_CHARACTER(type) char c_filename[512]; char c_mode[10]; char c_type[10]; cnfImpn(filename, filename_length, 512, c_filename); cnfImpn(mode, mode_length, 10, c_mode); cnfImpn(type, type_length, 10, c_type); try { lib_init(); *handle = hsimp.request(); //HSession& hs = hsess.get(*dbahandle); HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_messaggi(*handle, c_filename, c_mode, c_type)); h.api = new fortran::MsgAPI(c_filename, c_mode, c_type); return fortran::success(); } catch (error& e) { hsimp.release(*handle); return fortran::error(e); } } /** * Ends a session with DBALLE * * @param handle * Handle to the session to be closed. */ F77_INTEGER_FUNCTION(idba_fatto)(INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_fatto()); hsimp.release(*handle); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Reset the database contents, loading default report informations from a file. * * It only works in rewrite mode. * * @param handle * Handle to a DBALLE session * @param repinfofile * CSV file with the default report informations. See dba_reset() * documentation for the format of the file. * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_scopa)(INTEGER(handle), CHARACTER(repinfofile) TRAIL(repinfofile)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(repinfofile) char fname[PATH_MAX]; cnfImpn(repinfofile, repinfofile_length, PATH_MAX, fname); fname[PATH_MAX - 1] = 0; try { HSimple& h = hsimp.get(*handle); if (fname[0] == 0) { IF_TRACING(h.trace.log_scopa()); h.api->scopa(0); } else { IF_TRACING(h.trace.log_scopa(fname)); h.api->scopa(fname); } return fortran::success(); } catch (error& e) { return fortran::error(e); } } /**@name idba_enq* * @anchor idba_enq * Functions used to read the output values of the DBALLE action routines * @{ */ /** * Read one integer value from the output record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to query. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * Where the value will be returned * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_enqi)( INTEGER(handle), CHARACTER(parameter), INTEGER(value) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_INTEGER(value) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); *value = h.api->enqi(parm); tofortran(*value); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Read one byte value from the output record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to query. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * Where the value will be returned * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_enqb)( INTEGER(handle), CHARACTER(parameter), BYTE(value) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_BYTE(value) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); *value = h.api->enqb(parm); if (*value == fortran::API::missing_byte) *value = MISSING_BYTE; return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Read one real value from the output record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to query. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * Where the value will be returned * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_enqr)( INTEGER(handle), CHARACTER(parameter), REAL(value) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_REAL(value) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); *value = h.api->enqr(parm); if (*value == fortran::API::missing_float) *value = MISSING_REAL; return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Read one real*8 value from the output record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to query. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * Where the value will be returned * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_enqd)( INTEGER(handle), CHARACTER(parameter), DOUBLE(value) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_DOUBLE(value) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); *value = h.api->enqd(parm); if (*value == fortran::API::missing_double) *value = MISSING_DOUBLE; return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Read one character value from the output record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to query. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * Where the value will be returned * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_enqc)( INTEGER(handle), CHARACTER(parameter), CHARACTER(value) TRAIL(parameter) TRAIL(value)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_CHARACTER(value) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); const char* v = h.api->enqc(parm); if (!v) { if (value_length > 0) { // The missing string value has been defined as a // null byte plus blank padding. value[0] = 0; memset(value+1, ' ', value_length - 1); } } else cnfExprt(v, value, value_length); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /*@}*/ /**@name idba_set* * @anchor idba_set * Functions used to read the input values for the DBALLE action routines *@{*/ /** * Set one integer value into the input record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to set. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * The value to assign to the parameter * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_seti)( INTEGER(handle), CHARACTER(parameter), INTEGER(value) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_INTEGER(value) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); if (*value == MISSING_INT) { TRACEMISSING("int"); IF_TRACING(h.trace.log_unset(parm)); h.api->unset(parm); } else { IF_TRACING(h.trace.log_set(parm, *value)); h.api->seti(parm, *value); } return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Set one byte value into the input record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to set. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * The value to assign to the parameter * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_setb)( INTEGER(handle), CHARACTER(parameter), BYTE(value) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_BYTE(value) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); if (*value == MISSING_BYTE) { TRACEMISSING("byte"); IF_TRACING(h.trace.log_unset(parm)); h.api->unset(parm); } else { IF_TRACING(h.trace.log_set(parm, *value)); h.api->setb(parm, *value); } return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Set one real value into the input record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to set. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * The value to assign to the parameter * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_setr)( INTEGER(handle), CHARACTER(parameter), REAL(value) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_REAL(value) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); if (*value == MISSING_REAL) { TRACEMISSING("real"); IF_TRACING(h.trace.log_unset(parm)); h.api->unset(parm); } else { IF_TRACING(h.trace.log_set(parm, *value)); h.api->setr(parm, *value); } return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Set one real*8 value into the input record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to set. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * The value to assign to the parameter * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_setd)( INTEGER(handle), CHARACTER(parameter), DOUBLE(value) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_DOUBLE(value) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); if (*value == MISSING_DOUBLE) { TRACEMISSING("double"); IF_TRACING(h.trace.log_unset(parm)); h.api->unset(parm); } else { IF_TRACING(h.trace.log_set(parm, *value)); h.api->setd(parm, *value); } return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Set one character value into the input record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to set. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @param value * The value to assign to the parameter * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_setc)( INTEGER(handle), CHARACTER(parameter), CHARACTER(value) TRAIL(parameter) TRAIL(value)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_CHARACTER(value) char parm[20]; char val[255]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; cnfImpn(value, value_length, 254, val); val[254] = 0; try { HSimple& h = hsimp.get(*handle); if (val[0] == 0) { TRACEMISSING("char"); IF_TRACING(h.trace.log_unset(parm)); h.api->unset(parm); } else { IF_TRACING(h.trace.log_set(parm, val)); h.api->setc(parm, val); } return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Shortcut function to set query parameters to the anagraphical context * * @param handle * Handle to a DBALLE session * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_setcontextana)( INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_func("setcontextana")); h.api->setcontextana(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Shortcut function to read level data. * * @param handle * Handle to a DBALLE session * @retval ltype * Level type from the output record * @retval l1 * L1 from the output record * @retval l2 * L2 from the output record * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_enqlevel)( INTEGER(handle), INTEGER(ltype1), INTEGER(l1), INTEGER(ltype2), INTEGER(l2)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(ltype1) GENPTR_INTEGER(l1) GENPTR_INTEGER(ltype2) GENPTR_INTEGER(l2) try { HSimple& h = hsimp.get(*handle); h.api->enqlevel(*ltype1, *l1, *ltype2, *l2); tofortran(*ltype1); tofortran(*l1); tofortran(*ltype2); tofortran(*l2); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Shortcut function to set level data. * * @param handle * Handle to a DBALLE session * @param ltype * Level type to set in the input record * @param l1 * L1 to set in the input record * @param l2 * L2 to set in the input record * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_setlevel)( INTEGER(handle), INTEGER(ltype1), INTEGER(l1), INTEGER(ltype2), INTEGER(l2)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(ltype1) GENPTR_INTEGER(l1) GENPTR_INTEGER(ltype2) GENPTR_INTEGER(l2) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_setlevel( fromfortran(*ltype1), fromfortran(*l1), fromfortran(*ltype2), fromfortran(*l2))); h.api->setlevel( fromfortran(*ltype1), fromfortran(*l1), fromfortran(*ltype2), fromfortran(*l2)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Shortcut function to read time range data. * * @param handle * Handle to a DBALLE session * @retval ptype * P indicator from the output record * @retval p1 * P1 from the output record * @retval p2 * P2 from the output record * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_enqtimerange)( INTEGER(handle), INTEGER(ptype), INTEGER(p1), INTEGER(p2)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(ptype) GENPTR_INTEGER(p1) GENPTR_INTEGER(p2) try { HSimple& h = hsimp.get(*handle); h.api->enqtimerange(*ptype, *p1, *p2); tofortran(*ptype); tofortran(*p1); tofortran(*p2); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Shortcut function to set time range data. * * @param handle * Handle to a DBALLE session * @param ptype * P indicator to set in the input record * @param p1 * P1 to set in the input record * @param p2 * P2 to set in the input record * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_settimerange)( INTEGER(handle), INTEGER(ptype), INTEGER(p1), INTEGER(p2)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(ptype) GENPTR_INTEGER(p1) GENPTR_INTEGER(p2) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_settimerange(fromfortran(*ptype), fromfortran(*p1), fromfortran(*p2))); h.api->settimerange( fromfortran(*ptype), fromfortran(*p1), fromfortran(*p2)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Shortcut function to read date information. * * @param handle * Handle to a DBALLE session * @retval year * Year from the output record * @retval month * Month the output record * @retval day * Day the output record * @retval hour * Hour the output record * @retval min * Minute the output record * @retval sec * Second the output record * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_enqdate)( INTEGER(handle), INTEGER(year), INTEGER(month), INTEGER(day), INTEGER(hour), INTEGER(min), INTEGER(sec)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(year) GENPTR_INTEGER(month) GENPTR_INTEGER(day) GENPTR_INTEGER(hour) GENPTR_INTEGER(min) GENPTR_INTEGER(sec) try { HSimple& h = hsimp.get(*handle); h.api->enqdate(*year, *month, *day, *hour, *min, *sec); tofortran(*year), tofortran(*month), tofortran(*day); tofortran(*hour), tofortran(*min), tofortran(*sec); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Shortcut function to set date information. * * @param handle * Handle to a DBALLE session * @param year * Year to set in the input record * @param month * Month to set in the input * @param day * Day to set in the input * @param hour * Hour to set in the input * @param min * Minute to set in the input * @param sec * Second to set in the input * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_setdate)( INTEGER(handle), INTEGER(year), INTEGER(month), INTEGER(day), INTEGER(hour), INTEGER(min), INTEGER(sec)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(year) GENPTR_INTEGER(month) GENPTR_INTEGER(day) GENPTR_INTEGER(hour) GENPTR_INTEGER(min) GENPTR_INTEGER(sec) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_setdate( fromfortran(*year), fromfortran(*month), fromfortran(*day), fromfortran(*hour), fromfortran(*min), fromfortran(*sec))); h.api->setdate( fromfortran(*year), fromfortran(*month), fromfortran(*day), fromfortran(*hour), fromfortran(*min), fromfortran(*sec)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Shortcut function to set minimum date for a query. * * @param handle * Handle to a DBALLE session * @param year * Minimum year to set in the query * @param month * Minimum month to set in the query * @param day * Minimum day to set in the query * @param hour * Minimum hour to set in the query * @param min * Minimum minute to set in the query * @param sec * Minimum second to set in the query * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_setdatemin)( INTEGER(handle), INTEGER(year), INTEGER(month), INTEGER(day), INTEGER(hour), INTEGER(min), INTEGER(sec)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(year) GENPTR_INTEGER(month) GENPTR_INTEGER(day) GENPTR_INTEGER(hour) GENPTR_INTEGER(min) GENPTR_INTEGER(sec) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_setdate( fromfortran(*year), fromfortran(*month), fromfortran(*day), fromfortran(*hour), fromfortran(*min), fromfortran(*sec), "min")); h.api->setdatemin( fromfortran(*year), fromfortran(*month), fromfortran(*day), fromfortran(*hour), fromfortran(*min), fromfortran(*sec)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Shortcut function to set maximum date for a query. * * @param handle * Handle to a DBALLE session * @param year * Maximum year to set in the query * @param month * Maximum month to set in the query * @param day * Maximum day to set in the query * @param hour * Maximum hour to set in the query * @param min * Maximum minute to set in the query * @param sec * Maximum second to set in the query * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_setdatemax)( INTEGER(handle), INTEGER(year), INTEGER(month), INTEGER(day), INTEGER(hour), INTEGER(min), INTEGER(sec)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(year) GENPTR_INTEGER(month) GENPTR_INTEGER(day) GENPTR_INTEGER(hour) GENPTR_INTEGER(min) GENPTR_INTEGER(sec) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_setdate( fromfortran(*year), fromfortran(*month), fromfortran(*day), fromfortran(*hour), fromfortran(*min), fromfortran(*sec), "max")); h.api->setdatemax( fromfortran(*year), fromfortran(*month), fromfortran(*day), fromfortran(*hour), fromfortran(*min), fromfortran(*sec)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /*@}*/ /** * Remove one parameter from the input record * * @param handle * Handle to a DBALLE session * @param parameter * Parameter to remove. It can be the code of a WMO variable prefixed by \c * "B" (such as \c "B01023"); the code of a QC value prefixed by \c "*B" * (such as \c "*B01023") or a keyword among the ones defined in \ref * dba_record_keywords * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_unset)( INTEGER(handle), CHARACTER(parameter) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) GENPTR_INTEGER(err) char parm[20]; cnfImpn(parameter, parameter_length, 19, parm); parm[19] = 0; try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_unset(parm)); h.api->unset(parm); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Remove all B* parameters from the input record * * @param handle * Handle to a DBALLE session */ F77_INTEGER_FUNCTION(idba_unsetb)( INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_func("unsetb")); h.api->unsetb(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Remove all parameters from the input record * * @param handle * Handle to a DBALLE session */ F77_INTEGER_FUNCTION(idba_unsetall)( INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_func("unsetall")); h.api->unsetall(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Count the number of elements in the anagraphical storage, and start a new * anagraphical query. * * Resulting anagraphical data can be retrieved with idba_elencamele() * * @param handle * Handle to a DBALLE session * @param count * The count of elements * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_quantesono)( INTEGER(handle), INTEGER(count)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(count) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_quantesono()); *count = h.api->quantesono(); IF_TRACING(fortran::log_result(*count)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Iterate through the anagraphical data. * * Every invocation of this function will return a new anagraphical data, or * fill fail with code DBA_ERR_NOTFOUND when there are no more anagraphical * data available. * * @param handle * Handle to a DBALLE session * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_elencamele)(INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_func("elencamele")); h.api->elencamele(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Submit a query to the database. * * The query results can be accessed with calls to idba_dammelo. * * @param handle * Handle to a DBALLE session * @retval count * Number of values returned by the function * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_voglioquesto)( INTEGER(handle), INTEGER(count)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(count) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_voglioquesto()); *count = h.api->voglioquesto(); IF_TRACING(fortran::log_result(*count)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Iterate through the query results data. * * Every invocation of this function will return a new result, or fill fail * with code DBA_ERR_NOTFOUND when there are no more results available. * * @param handle * Handle to a DBALLE session * @retval parameter * Contains the ID of the parameter retrieved by this fetch * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_dammelo)( INTEGER(handle), CHARACTER(parameter) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_dammelo()); const char* res = h.api->dammelo(); IF_TRACING(fortran::log_result(res)); if (!res) cnfExprt("", parameter, parameter_length); else cnfExprt(res, parameter, parameter_length); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Insert a new item in the database. * * This function will fail if the database is open in data readonly mode, and * it will refuse to overwrite existing values if the database is open in data * add mode. * * If the database is open in pseudoana reuse mode, the pseudoana values * provided on input will be used to create a pseudoana record if it is * missing, but will be ignored if it is already present. If it is open in * pseudoana rewrite mode instead, the pseudoana values on input will be used * to replace all the existing pseudoana values. * * @param handle * Handle to a DBALLE session * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_prendilo)( INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_func("prendilo")); h.api->prendilo(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Remove all selected items from the database. * * This function will fail unless the database is open in data rewrite mode. * * @param handle * Handle to a DBALLE session * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_dimenticami)( INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_func("dimenticami")); h.api->dimenticami(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /**@name QC functions * @anchor qc * Functions used to manipulate QC data. * * All these functions require some context data about the variable, which is * automatically available when the variable just came as the result of an * idba_dammelo() or has just been inserted with an idba_prendilo(). *@{ */ F77_INTEGER_FUNCTION(idba_voglioancora)(INTEGER(handle), INTEGER(count)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(count) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_voglioancora()); *count = h.api->voglioancora(); IF_TRACING(fortran::log_result(*count)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Retrieve QC informations from the last variable returned by idba_dammelo(). * * @param handle * Handle to a DBALLE session * @retval parameter * Contains the ID of the parameter retrieved by this fetch * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_ancora)( INTEGER(handle), CHARACTER(parameter) TRAIL(parameter)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(parameter) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_ancora()); const char* res = h.api->ancora(); IF_TRACING(fortran::log_result(res)); if (!res) cnfExprt("", parameter, parameter_length); else cnfExprt(res, parameter, parameter_length); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Insert new QC informations for a variable of the current record. * * QC informations inserted are all those set by the functions idba_seti(), * idba_setc(), idba_setr(), idba_setd(), using an asterisk in front of the * variable name. * * Contrarily to idba_prendilo(), this function resets all the QC informations * (but only the QC informations) previously set in input, so the values to be * inserted need to be explicitly set every time. * * This function will fail if the database is open in QC readonly mode, and it * will refuse to overwrite existing values if the database is open in QC add * mode. * * The variable referred by the QC informations can be specified in three ways: * * \li by variable code, using ::idba_setc(handle, "*var", "Bxxyyy") * \li by variable id, using ::idba_seti(handle, "*data_id", id) * \li unspecified, will use the last variable returned by ::idba_dammelo * * @param handle * Handle to a DBALLE session * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_critica)( INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_func("critica")); h.api->critica(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } /** * Remove QC informations for a variable of the current record. * * The QC informations to be removed are set with: * \code * idba_setc(handle, "*varlist", "*B33021,*B33003"); * \endcode * * The variable referred by the QC informations can be specified in three ways: * * \li by variable code, using ::idba_setc(handle, "*var", "Bxxyyy") * \li by variable id, using ::idba_seti(handle, "*data_id", id) * \li unspecified, will use the last variable returned by ::idba_dammelo * * @param handle * Handle to a DBALLE session * @return * The error indicator for the function */ F77_INTEGER_FUNCTION(idba_scusa)(INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_func("scusa")); h.api->scusa(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } F77_INTEGER_FUNCTION(idba_messages_open_input)( INTEGER(handle), CHARACTER(filename), CHARACTER(mode), CHARACTER(format), LOGICAL(simplified) TRAIL(filename) TRAIL(mode) TRAIL(format)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(filename) GENPTR_CHARACTER(mode) GENPTR_CHARACTER(format) GENPTR_LOGICAL(simplified) char c_filename[512]; char c_mode[10]; char c_format[10]; cnfImpn(filename, filename_length, 511, c_filename); c_filename[511] = 0; cnfImpn(mode, mode_length, 9, c_mode); c_mode[9] = 0; cnfImpn(format, format_length, 9, c_format); c_format[9] = 0; try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_messages_open_input(c_filename, c_mode, c_format, *simplified)); h.api->messages_open_input(c_filename, c_mode, File::parse_encoding(c_format), *simplified); return fortran::success(); } catch (error& e) { return fortran::error(e); } } F77_INTEGER_FUNCTION(idba_messages_open_output)( INTEGER(handle), CHARACTER(filename), CHARACTER(mode), CHARACTER(format) TRAIL(filename) TRAIL(mode) TRAIL(format)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(filename) GENPTR_CHARACTER(mode) GENPTR_CHARACTER(format) char c_filename[512]; char c_mode[10]; char c_format[10]; cnfImpn(filename, filename_length, 511, c_filename); c_filename[511] = 0; cnfImpn(mode, mode_length, 9, c_mode); c_mode[9] = 0; cnfImpn(format, format_length, 9, c_format); c_format[9] = 0; try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_messages_open_output(c_filename, c_mode, c_format)); h.api->messages_open_output(c_filename, c_mode, File::parse_encoding(c_format)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } F77_INTEGER_FUNCTION(idba_messages_read_next)(INTEGER(handle), LOGICAL(found)) { GENPTR_INTEGER(handle) GENPTR_LOGICAL(found) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_messages_read_next()); *found = h.api->messages_read_next(); IF_TRACING(fortran::log_result(*found)); return fortran::success(); } catch (error& e) { return fortran::error(e); } } F77_INTEGER_FUNCTION(idba_messages_write_next)(INTEGER(handle), CHARACTER(template_name) TRAIL(template_name)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(template_name) char c_template_name[64]; cnfImpn(template_name, template_name_length, 63, c_template_name); c_template_name[63] = 0; try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_messages_write_next(c_template_name)); h.api->messages_write_next(c_template_name); return fortran::success(); } catch (error& e) { return fortran::error(e); } } F77_INTEGER_FUNCTION(idba_remove_all)( INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); IF_TRACING(h.trace.log_func("remove_all")); h.api->remove_all(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } F77_INTEGER_FUNCTION(idba_spiegal)( INTEGER(handle), INTEGER(ltype1), INTEGER(l1), INTEGER(ltype2), INTEGER(l2), CHARACTER(result) TRAIL(result)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(ltype1) GENPTR_INTEGER(l1) GENPTR_INTEGER(ltype2) GENPTR_INTEGER(l2) GENPTR_CHARACTER(result) try { HSimple& h = hsimp.get(*handle); const char* res = h.api->spiegal(*ltype1, *l1, *ltype2, *l2); cnfExprt(res, result, result_length); return fortran::success(); } catch (error& e) { return fortran::error(e); } } F77_INTEGER_FUNCTION(idba_spiegat)( INTEGER(handle), INTEGER(ptype), INTEGER(p1), INTEGER(p2), CHARACTER(result) TRAIL(result)) { GENPTR_INTEGER(handle) GENPTR_INTEGER(ptype) GENPTR_INTEGER(p1) GENPTR_INTEGER(p2) GENPTR_CHARACTER(result) try { HSimple& h = hsimp.get(*handle); const char* res = h.api->spiegat(*ptype, *p1, *p2); cnfExprt(res, result, result_length); return fortran::success(); } catch (error& e) { return fortran::error(e); } } F77_INTEGER_FUNCTION(idba_spiegab)( INTEGER(handle), CHARACTER(varcode), CHARACTER(value), CHARACTER(result) TRAIL(varcode) TRAIL(value) TRAIL(result)) { GENPTR_INTEGER(handle) GENPTR_CHARACTER(varcode) GENPTR_CHARACTER(value) GENPTR_CHARACTER(result) char s_varcode[10]; char s_value[300]; cnfImpn(varcode, varcode_length, 9, s_varcode); s_varcode[9] = 0; cnfImpn(value, value_length, 299, s_value); s_value[299] = 0; try { HSimple& h = hsimp.get(*handle); const char* res = h.api->spiegab(s_varcode, s_value); cnfExprt(res, result, result_length); return fortran::success(); } catch (error& e) { return fortran::error(e); } } F77_INTEGER_FUNCTION(idba_test_input_to_output)( INTEGER(handle)) { GENPTR_INTEGER(handle) try { HSimple& h = hsimp.get(*handle); h.api->test_input_to_output(); return fortran::success(); } catch (error& e) { return fortran::error(e); } } } /*@}*/ /* vim:set ts=4 sw=4: */ dballe-7.7/doc/0000755000175000017500000000000012653425053010365 500000000000000dballe-7.7/doc/Makefile.in0000644000175000017500000004457612652630066012373 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @DO_DOCS_TRUE@am__append_1 = libdballe.doxytags guide.pdf @DO_DOCS_TRUE@am__append_2 = c_api/index.html @DO_DBALLEF_TRUE@@DO_DOCS_TRUE@am__append_3 = fapi.pdf libdballef.doxytags @DO_DBALLEF_TRUE@@DO_DOCS_TRUE@am__append_4 = fortran_api/index.html @DO_DOCS_TRUE@@HAVE_LATEX2HTML_TRUE@am__append_5 = \ @DO_DOCS_TRUE@@HAVE_LATEX2HTML_TRUE@ fapi_html/index.html \ @DO_DOCS_TRUE@@HAVE_LATEX2HTML_TRUE@ guide_html/index.html subdir = doc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/m4_ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = libdballe.dox libdballef.dox CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(docdir)" DATA = $(doc_DATA) $(noinst_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libdballe.dox.in \ $(srcdir)/libdballef.dox.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FC = @FC@ FCFLAGS = @FCFLAGS@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDBALLEF_VERSION_INFO = @LIBDBALLEF_VERSION_INFO@ LIBDBALLE_VERSION_INFO = @LIBDBALLE_VERSION_INFO@ LIBOBJS = @LIBOBJS@ LIBPQ_CFLAGS = @LIBPQ_CFLAGS@ LIBPQ_LIBS = @LIBPQ_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ WREPORT_CFLAGS = @WREPORT_CFLAGS@ WREPORT_LIBS = @WREPORT_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_FC = @ac_ct_FC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_doxygen = @have_doxygen@ have_gperf = @have_gperf@ have_latex2html = @have_latex2html@ have_rst2html = @have_rst2html@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mysql_config = @mysql_config@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ tabledir = @tabledir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ guidesources = guide.tex intro.tex install.tex maintainance.tex troubleshooting.tex local.bib fapisources = fapi.tex ../dballe/core/record_keyword.tex ../dballe/msg/ltypes.tex ../dballe/msg/tranges.tex cdoxdeps = libdballe.dox \ ../dballe/libdballe.la \ ../dballe/msg/ltypes.dox \ ../dballe/msg/tranges.dox fortrandoxdeps = libdballef.dox \ ../fortran/libdballef.la LATEX2HTML = latex2html -local_icons doc_DATA = $(am__append_1) $(am__append_3) noinst_DATA = $(am__append_2) $(am__append_4) $(am__append_5) #mainpages += ../dballe/main-bufrex.dox mainpages = ../dballe/main-core.dox ../dballe/main-msg.dox \ ../dballe/main-db.dox TEXINPUTS = "$(srcdir)" EXTRA_DIST = $(guidesources) fapi.tex doxy2swig.py add_templates_to_manpage introduzione.odt CLEANFILES = libdballe.doxytags libdballef.doxytags {guide,fapi}.{ps,pdf,dvi,aux,bbl,idx,log,toc,blg} all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *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);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): libdballe.dox: $(top_builddir)/config.status $(srcdir)/libdballe.dox.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ libdballef.dox: $(top_builddir)/config.status $(srcdir)/libdballef.dox.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(docdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-docDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-docDATA uninstall-local .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-local install-docDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-docDATA uninstall-local .PRECIOUS: Makefile install-data-local: for pkg in c fortran; do \ test -d $${pkg}_api && \ $(mkinstalldirs) $(DESTDIR)$(docdir)/$${pkg}_api && \ find $${pkg}_api -type f -exec $(INSTALL_DATA) '{}' $(DESTDIR)$(docdir)/$${pkg}_api/ \; ; \ done || true for pkg in fapi_html guide_html; do \ test -d $$pkg && \ $(mkinstalldirs) $(DESTDIR)$(docdir)/$$pkg && \ find $$pkg -type f -exec $(INSTALL_DATA) '{}' $(DESTDIR)$(docdir)/$$pkg/ \; ; \ done || true uninstall-local: for pkg in c fortran; do \ rm -rf $(DESTDIR)$(docdir)/$${pkg}_api; \ done || true libwreport.doxytags: /usr/share/doc/libwreport-dev/libwreport.doxytags.gz zcat $< > $@ libdballe.doxytags c_api/index.html xml/index.xml: $(cdoxdeps) $(mainpages) doxygen $< libdballef.doxytags fortran_api/index.html: $(fortrandoxdeps) doxygen $< fapi_html/index.html: $(fapisources) $(LATEX2HTML) -dir fapi_html -split 1 -mkdir $< guide_html/index.html: $(guidesources) $(LATEX2HTML) -dir guide_html -split 1 -mkdir $< #fapi-quick.html: fapi-quick.rst ../dballe/core/dba_record_keyword.rst #fapi-quick.html: fapi-quick.rst # rst2html < $< > $@ %.ps: %.dvi TEXINPUTS="$(TEXINPUTS):" dvips $< -o %.pdf: %.tex pdflatex --shell-escape $< %.aux: %.tex TEXINPUTS="$(TEXINPUTS):" latex $< %.bbl: %.aux BIBINPUTS="$(TEXINPUTS):" bibtex `basename $< .aux` %.dvi: %.tex %.aux %.bbl TEXINPUTS="$(TEXINPUTS):" latex $< BIBINPUTS="$(TEXINPUTS):" bibtex `basename $< .tex` TEXINPUTS="$(TEXINPUTS):" latex $< # Additional dependencies for guide.dvi guide.dvi: $(guidesources) fapi.dvi: $(fapisources) clean-local: rm -rf {c,fortran}_api rm -rf xml rm -rf guide_html rm -rf fapi_html rm -f libwreport.doxytags rm -f doxygen_sqlite3.db # 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: dballe-7.7/doc/maintainance.tex0000644000175000017500000002336412652630043013462 00000000000000\section {Configuration} A normal \dballe{} installation normally requires very little configuration, namely only the parameters used to connect to the database. Those are either specified in the code with the functions {\tt dba\_db\_create} (from C) or {\tt idba\_presentati} (from Fortran), or in the commandline for {\tt dbadb}. If special needs arise, further parameters that usually have good and working default values can be altered via environment variables: \begin{description} \item[{\tt DBA\_TABLES}] specifies the directory where the various table files are looked for (all the table files excluding {\tt repinfo.csv}). If the variable is not present, the default is {\tt /usr/share/dballe}. \item[{\tt DBA\_REPINFO}] specifies the full path of the file {\tt repinfo.csv} to use when resetting the databse. If the variable is not present, the default is {\tt /etc/dballe/repinfo.csv}. \item[{\tt DBA\_VERBOSE}] enable verbose reporting of \dballe{} internals. The value is a bit mask where every bit corresponds to a different internal part of \dballe{}, and when a bit is 1 then verbose messages are printed when that part runs. All the currently defined bit meanings can be found in {\tt /usr/include/dballe/core/verbose.h}. The default is 0, which means no verbose reporting at all. \item[{\tt DBA\_AOF\_ENDIANNESS}] select a specific endianness to use when encoding AOF messages. The possible values are {\tt ARCH} (use the endianness of the current host), {\tt LE} (little endian) and {\tt BE} (big endian). If the variable is not present, then the default value is {\tt ARCH}. \end{description} \section {Commandline tools} All the tools have a manpage as well as online help. To get a list of the various commands provided by a tool, run it with the {\tt --help} option. To see mode details about a given command, use {\tt --help} after the name of the command, as in {\tt dbamsg dump --help}. The syntax {\tt dbamsg help dump} works as well. \subsection{dbatbl} {\tt dbatbl} is the tool to manage table files. It is useful for small table management tasks like searching table contents and expand entries. \subsection{dbamsg} {\tt dbamsg} is the tool to manage messages. It can display their contents, select messages from a file containing many of them, convert messages among different format, find differences among messages. \subsection{dbadb} {\tt dbadb} is the tool to manage the \dballe{} database. It can reset the database, import and export messages and dump the contents of the database. To import a BUFR file into the database, simply use: {\tt dbadb import file.bufr}. If it does not work, you probably need to add some switches with the parameters to connect to the database, like {\tt --user={\it user} } and {\tt --pass={\it password} }. \section {Managing tables} \dballe{} needs various kinds of data tables to work: \begin{description} \item[repinfo.csv] Contains informations about all the supported origins of data, including a text description, a short memo and the importance of the various kinds of data compared to the others. \item[dballe.txt] Contains the description of all the possible kinds of variables that can be handled by \dballe{}, with information such as text description, measurement units, number of digits used for encoding. It is usually referred as ``the local B table'', and is used for all internal representation and for exporting ``generic'' messages. \item[WMO B tables] Data description tables maintained by WMO that are used for encoding and decoding BUFR and CREX messages. \item[WMO D tables] Data grouping tables maintained by WMO that are used for encoding and decoding BUFR and CREX messages. \end{description} \subsection{repinfo.csv} The file {\tt repinfo.csv} is usually installed in {\tt /etc/dballe/} and is only read when creating or recreating a database. It is a table encoded in CSV format, where every line is a table row and table columns are separated by commas. No particular string escaping is supported, so no strings should contain a comma. This is an example {\tt repinfo.csv}: \begin{verbatim} 01,synop,report synottico,100,oss,0 02,metar,metar,80,oss,0 03,temp,radiosondaggio,100,oss,2 04,pilot,pilot,90,oss,2 09,boe,dati omdametrici,100,oss,31 10,ship,synop da nave,100,oss,1 11,tempship,temp da nave,100,oss,2 12,airep,airep,80,oss,4 13,amdar,amdar,100,oss,4 14,acars,acars,100,oss,4 104,ana_lm,valori analizzati LM,-1,ana,255 105,ana,analisi,-10,pre,255 106,pre_cleps_box1.5maxel001,previsti cosmo leps box 1.5 gradi valore max elemento 1,-1,pre,255 107,pre_lmn_box1.5med,previzione Lokal Model nudging box 1.5 gradi valore medio,-1,pre,255 108,pre_lmp_spnp0,previsione Lkal Model prognostica interpolato punto piu' vicino,-1,pre,255 255,generic,export generici da DB Meteo,1,oss,42 \end{verbatim} The file has six columns: \begin{enumerate} \item The report code. This is used to refer to this report type in all the internal representations. \item The mnemonic short name. It can be used to univocally refer to this report type in a way that is easier to remember than the report code. \item The complete name. \item The report priority. When more data are found in the same physical point but with different report types, the report priority can be used to select a best value among them. \item FIXME: Unknown: "descriptor" \item FIXME: Unknown: "table a" \end{enumerate} \subsection{dballe.txt} The file {\tt dballe.txt} is usually installed in {\tt /usr/share/dballe/} and contains the variable definitions used when working with \dballe{}. {\tt dballe.txt} is used at least for these tasks: \begin{itemize} \item Encoding values in the \dballe{} database. \item Accessing values from the Fortran API\cite{FAPI}. \item Encoding values in memory as intermediate representation when converting among different encodings. \item Encoding values for exporting to BUFR and CREX messages using the non-standard 'generic' template. \end{itemize} The file contains 8 columns with fixed width: \begin{enumerate} \item The variable code to use to refer to this measure (6 characters). \item The description (64 characters). \item The measure unit to use when encoding to BUFR (24 characters). \item The scale to use when encoding to BUFR (3 characters). \item The reference value to use when encoding to BUFR (12 characters). \item The width of the field in \emph{bits} to use when encoding to BUFR (3 characters). \item The measure unit to use when encoding to CREX (24 characters). \item The scale to use when encoding to CREX (3 characters). \item The width of the field in \emph{bytes} to use when encoding to CREX, not including the leading minus sign of negative numbers (10 characters). \end{enumerate} There is a space character before each column, including before the first one. Elements can be freely added to {\tt dballe.txt} paying attention to respecting the file format. There is no need for indexing, and the local B table is read and parsed the first time that a program needs a value from it, and cached in memory for the entire lifetime of the program. \subsection{WMO B tables and WMO D tables} To be able to encode and decode standard BUFR and CREX messages there is a need of extra tables provided by the data center originating the data. These tables are normally to be installed in {\tt /usr/share/dballe} and have special names so that they can be easily identified from the header information stored in the BUFR or CREX message. The format of these tables, in the case of B tables is analogous to the format of {\tt dballe.txt}. BUFR tables usually do not contain the last 3 fields which are specific to CREX encoding, while CREX tables also contain BUFR encoding informations. WMO D tables contain instead definitions of groups of variables to use to reduce the size of a BUFR or CREX message. The file contains 3 fixed width columns, and the rows are organised in records starting with a line with 3 values followed by one or more continuation lines with only one value. The start of a D table record contains: \begin{enumerate} \item D table code used to refer to this group of variables (6 characters). \item Number of elements in the expansion (2 characters). \item First element of the expansion (6 characters). \end{enumerate} The continuation rows of a D table only contains one element of the expansion. An element in the expansion could consist of a B table element, a D table element or occasionally some C table references or repetition codes as explained in the BUFR and CREX documentation. Like the WMO B table, in the WMO D table there is a space character before each column, including before the first one. \dballe{} does not require indexing to access the B and D tables used for encoding: if new B and D tables needs to be installed, they just need to be copied in {\tt /usr/share/dballe} with the right name. The name of the BUFR WMO B and D table files is in the form {\tt t00000aaabbbccdd}, where: \begin{description} \item[{\tt t}] is ``B'' or ``D'' (WMO B table or WMO D table). % FIXME: what is aaa? \item[{\tt aaa}] is normally 0. \item[{\tt bbb}] is the 3 digit code of the originating center. \item[{\tt cc}] is the 2 digit code of the master table used to create the BUFR message. \item[{\tt dd}] is the 2 digit code of the local table used to augment the master table. \end{description} The name of CREX WMO B and D tables is instead in the form {\tt taabbcc}, where: \begin{description} \item[{\tt t}] is ``B'' or ``D'' (WMO B table or WMO D table). \item[{\tt aa}] is the 2 digit code of the master table used to create the CREX message. \item[{\tt bb}] is the 2 digit CREX edition number. \item[{\tt cc}] is the 2 digit code of the table used to create the CREX message. \end{description} dballe-7.7/doc/fapi.tex0000644000175000017500000017536512652630043011763 00000000000000% % Editorial notes are found in the 'Introduction' chapter, marked with a % comment to find them more easily % %\documentclass[draft,a4paper]{book} %\documentclass[final,a4wide]{book} %\documentclass[final,12pt,a4paper,twoside]{book} \documentclass[final,12pt,a4paper,twoside]{book} %\usepackage[italian]{babel} \usepackage[ascii]{inputenc} \usepackage[T1]{fontenc} \usepackage{graphicx} \usepackage{moreverb} \usepackage{ifthen} % Include alcuni simboli non piú standard ma usati da gnuplot \usepackage{subfigure} \usepackage{epsfig} \usepackage{longtable} \title{DB-ALLe Guide of the Fortran API} \author{Enrico Zini \hfil {\tt enrico@enricozini.com}} % Copyright: GNU GPL v2 or later. \newcommand{\dballe}{{\tt DB-ALLe}} \newcommand{\srcinsert}[1]{% {\scriptsize \verbatimtabinput[4]{#1} }} %\newlength{\savedmarginparwidth} \newcommand{\figures}[2][!]{% \smallskip %\setlength{\savedmarginparwidth}{\marginparwidth} %\setlength{\marginparwidth}{0pt} \begin{minipage}[c]{\textwidth} \ifthenelse{\equal{#1}{!}}{}{#1:\\} #2 \end{minipage} \medskip %\setlength{\marginparwidth}{\savedmarginparwidth} } \makeindex \begin{document} \setlength{\oddsidemargin}{0pt} \setlength{\evensidemargin}{0pt} \bibliographystyle{plain} \maketitle %\begin{abstract} %This document is a quick introduction to the Fortran API of DB-ALLe. It %proceeds step by step to introducing different parts of the library using %commented example code. %\end{abstract} \tableofcontents %\listoffigures %\listoftables \chapter {Introduction} \label{ch-intro} \dballe{} is a fast, temporary, on-disk database where meteorological data can be stored, searched, retrieved and updated. To make computation easier, data is stored as physical data, that is, as measures of a variable in a specific point of space and time, rather than as a sequence of reports. This is a quick introduction to \dballe{}. It is intended as a quick read to get up to speed, and as a quick reference for everyday use. % Editorial notes This guide contains examples for all routines, plus examples for all known common usage patterns of dballe. Also, commented Fortran code is preferred to long explanations whenever it makes sense. Other documentation can be found in \cite{UserGuide} and \cite{LibDoc}. \chapter {Basic concepts} \label{ch-concepts} \section{Connections, sessions and handles} \dballe{} stores meteorological values in a database. This database can be optionally shared or accessed using the network. You contact \dballe{} by creating a \emph{connection}, and you work in \dballe{} using one or more \emph{sessions}. A connection is an established link between your program and \dballe{}, and you usually open it at the beginning of your work and close it at the end. Within a connection you can create many working sessions. This is very useful because it allows to do different things at the same time, like reading a set of values while writing computed results. You can also set some safety features on sessions: for example, when you create a session for reading values you can set it to disable all writes, which helps you catch some programming mistakes. You refer to the connection and the sessions using \emph{handles}. A handle is just an integer value that you use when you need to refer to something that is not otherwise representable in any Fortran data type. When you create a connection or a session, \dballe{} will give you the integer handle that you will later use to refer to it. \section {Pseudoana} Values in \dballe{} are associated to informations about their source, such as what kind of station generated the data and some characteristics of the station. These informations are called \emph{pseudoana} informations, to suggest that they are something similar to anagraphical informations about the sources of the values. A pseudoana entry is uniquely identified by: \begin{itemize} \item \emph{latitude}. \item \emph{longitude}. \item \emph{station identifier} (if the station is mobile). \end{itemize} \section {Station values} Each \emph{pseudoana} entry can have zero or more values associated to it. They are just like measured variables (see \ref{basic-values}), but lack date, time, level, and time range information. They can be used to store station attributes, like the height above sea level, or the center operating it. The interface to work with station values is the same as the interface to work with normal values, except that date, time, level, and timerange information are not set when inserting or querying data, and \texttt{idba\_setcontextana} is called instead (see \ref{fun-setcontextana}), to signal the intention of working with station values. See section \ref{sec-querying} for examples on how to work with values. \section {Level or layer} The vertical coordinate of a value in \dballe{} is described using a level description or a layer description. A level is defined univocally by a code table (\texttt{leveltype1}) and a numerical value (\texttt{l1}). A layer is defined univocally by its two bounding levels (\texttt{leveltype1}, \texttt{l1}, \texttt{leveltype2}, \texttt{l2}). See \ref{levels} for a description of the level types and associated level values. \section {Time range} Another characteristic of a value in \dballe{} is the time period to which the datum refers: it can be, for example, a value measured in a specific instant, or a cumulated or averaged value over an interval of time. The time range is defined by a table code (\texttt{pindicator}) and two numerical values (\texttt{p1} and \texttt{p2}, see \ref{tranges}). \section {Values} \label{basics-values} The main work of \dballe{} is to store and access \emph{measured values}. A measured value is a datum that can be expressed as a floating point (single or double precision), integer, character or byte, depending on what value it measures. Every datum is univocally defined by a system of coordinates with 7 dimensions: \begin{enumerate} \item The variable \emph{type}, which describes the nature of the variable, such as what it measures and the units used for measuring. It is identified by a \emph{local B table descriptor} (see \ref{btable}). \item The \emph{date and time} of validity of the datum, be it observed, forecast or estimated. \item \emph{pseudoana} information about what generated the value (also defining its x and y coordinates). \item The vertical coordinates in space, as a description of the \emph{level layer}. \item The \emph{time range} of the measurement. \item A \emph{network} or \emph{report} type, defining an homogeneous group of stations with the same kind of measures and management (for example: synop, metar, a specific kind of forecast...). \end{enumerate} You can find a list of all current B table descriptors in \ref{btable}. The type of report implicitly defines a priority of the measured value over other equivalent values. This can be used to select a ``best value'' from a specific set of coordinates, where for example, values measured by synoptic stations are preferred over values measured by a satellite, which in turn is preferred over a value computed by a forecast model. Priorities associated to the report type can be customized when creating the database (see \ref{fun-idba_scopa}). Every measured value in \dballe{} can be assigned any number of extra attributes, which can be used, for example, for quality control. \dballe{} also supports storing values \emph{about} a station (such as station height, or station name). These are called \emph{pseudoana values} and are handled just like values, with the exception that vertical coordinates, datetime and time range have no meanings and are forced to default values. Pseudoana values, just like normal values in \dballe{}, can have attributes and any B code. It is possible to have pseudoana values for a station on different networks, although this is rarely needed and the {\tt ana} network is normally used for pseudoana values. See section \ref{sec-querying} for examples on how to work with values. \section {Attributes} Values in \dballe{} are also associated to zero or more \emph{attributes}. An attribute is a value that describes an aspect of a variable, like for example a confidence interval. Attributes in \dballe{} consist on a value and a local B table descriptor, which describes the nature of the variable, such as what it represents and the units in which it is represented. Attributes are uniquely identified by the variable they refer to and the B table descriptor of the attribute. As a consequence, you can only have one attribute per value with a specific B table descriptor. This means that, for example, a variable can have at most one confidence interval attribute. See section \ref{sec-attrs} for examples on how to handle attributes. \dballe{} defines some extra code tables to use as values for attributes: a list is provided in section \ref{extract}. \section {Input, output, actions} \label{basics-inout} Work with \dballe{} happens using \emph{action routines}. An action routine typically reads some input, performs an action and produces some output. Example of action routines are {\tt idba\_voglioquesto} to query data from a database and {\tt idba\_prendilo} to write data into the database. The input and the output of action routines are collections of parameters which have a name and a value. A list of parameters can be found in \ref{parmtable}. You can set the input parameters using the {\tt idba\_set*} functions: \label{fun-idba_set} \begin{description} \item[{\tt idba\_seti(handle, "param", intvalue)}] Set the input parameter to the integer value {\tt intvalue} \item[{\tt idba\_setc(handle, "param", charvalue)}] Set the input parameter to the character value {\tt charvalue} \item[{\tt idba\_setr(handle, "param", realvalue)}] Set the input parameter to the real value {\tt realvalue} \item[{\tt idba\_setd(handle, "param", doublevalue)}] Set the input parameter to the real*8 value {\tt doublevalue} \item[{\tt idba\_setcontextana(handle)}] \label{fun-setcontextana} Sets the date, time, level and time range in the input record to some magic values, to signal that we are going to work with station attributes instead of normal values. \end{description} You can read the output parameters using the {\tt idba\_enq*} functions: \label{fun-idba_enq} \begin{description} \item[{\tt idba\_enqi(handle, "param", intvalue)}] Read the output parameter into the integer value {\tt intvalue} \item[{\tt idba\_enqc(handle, "param", charvalue)}] Read the output parameter into the character value {\tt charvalue} \item[{\tt idba\_enqr(handle, "param", realvalue)}] Read the output parameter into the real value {\tt realvalue} \item[{\tt idba\_enqd(handle, "param", doublevalue)}] Read the output parameter into the real*8 value {\tt doublevalue} \end{description} Note that all {\tt idba\_set} functions set input parameters, while all {\tt idb\_enq*} functions read output parameters. You cannot read input parameters or set output parameters: that is the job of action routines. In other words, input and output parameters are different things. In this code: \begin{verbatim} c A possible misunderstanding ierr = idba_seti(handle, "height", 1) ierr = idba_enqi(handle, "height", val) \end{verbatim} the value of {\tt val} after the {\tt idba\_enqi} will not probably be 1, and it could be either a value indicating ``missing value'' (in case no {\tt height} parameter is set in the output parameters) or a {\tt height} value previously retrieved by an action routine. To reset one input parameter you can use {\tt idba\_unset}: \label{fun-idba_unset} \begin{verbatim} c ... c We don't want to limit results by latitude this time ierr = idba_unset(handle, "latmin") ierr = idba_unset(handle, "latmax") ierr = idba_voglioquesto(handle, count) \end{verbatim} Alternatively, you can reset an input parameter by setting it to one of the special ``missing value'' values listed below. To reset all input parameters you can use {\tt idba\_unsetall}: \label{fun-idba_unsetall} \begin{verbatim} c Restart the query from scratch ierr = idba_unsetall(handle) ierr = idba_setd(handle, "latmin", 10.D0) c ... \end{verbatim} To reset only Bxxyyy variables you can use {\tt idba\_unsetb}: \label{fun-idba_unsetall} \begin{verbatim} c Insert a new variable with the old station, level and so on ierr = idba_unsetb(handle) ierr = idba_setd(handle, "B12101", 21.5) c ... \end{verbatim} There is no way to reset output parameters: it is not needed since all action routines will get rid of old output values before producing new ones. In case one of the {\tt idba\_enq*} functions is called on a parameter which does not exist, it will return a special value that indicates ``missing value''. This is a list of such special values: \begin{tabular}{|l|l|} \hline {\em Data type} & {\em Missing value indicator} \\ \hline String & "" \\ Int & 0x7fffffff \\ Real & -1.1754944E-38 \\ Double & -2.22507E-308 \\ \hline \end{tabular} \subsection {Input/output shortcuts} \label{fun-shortcuts} There are a few functions that are shortcuts to other input and output functions: \begin{description} \item[{\tt idba\_enqdate(handle, year, month, day, hour, minute, second)}] is a shortcut to: \begin{verbatim} idba_enqi(handle, "year", year) idba_enqi(handle, "month", month) idba_enqi(handle, "day", day) idba_enqi(handle, "hour", hour) idba_enqi(handle, "min", minute) idba_enqi(handle, "sec", second) \end{verbatim} \item[{\tt idba\_setdate(handle, year, month, day, hour, minute, second)}] is a shortcut to: \begin{verbatim} idba_seti(handle, "year", year) idba_seti(handle, "month", month) idba_seti(handle, "day", day) idba_seti(handle, "hour", hour) idba_seti(handle, "min", minute) idba_seti(handle, "sec", second) \end{verbatim} \item[{\tt idba\_enqlevel(handle, type1, l1, type2, l2)}] is a shortcut to: \begin{verbatim} idba_enqi(handle, "leveltype1", type1) idba_enqi(handle, "l1", l1) idba_enqi(handle, "leveltype2", type2) idba_enqi(handle, "l2", l2) \end{verbatim} \item[{\tt idba\_setlevel(handle, type1, l1, type2, l2)}] is a shortcut to: \begin{verbatim} idba_seti(handle, "leveltype1", type1) idba_seti(handle, "l1", l1) idba_seti(handle, "leveltype2", type2) idba_seti(handle, "l2", l2) \end{verbatim} \item[{\tt idba\_enqtimerange(handle, type, p1, p2)}] is a shortcut to: \begin{verbatim} idba_enqi(handle, "pindicator", type) idba_enqi(handle, "p1", p1) idba_enqi(handle, "p2", p2) \end{verbatim} \item[{\tt idba\_settimerange(handle, type, p1, p2)}] is a shortcut to: \begin{verbatim} idba_seti(handle, "pindicator", type) idba_seti(handle, "p1", p1) idba_seti(handle, "p2", p2) \end{verbatim} \end{description} \section {API invariants} \label{fun-error} \begin{itemize} \item All errors are reported as function return values \item All results are reported as output parameters \item All functions {\tt idba\_set*} set the input of action routines \item All functions {\tt idba\_enq*} get the output of action routines \end{itemize} \section {Error management} Errors can be handled by checking the return value of every function: \begin{verbatim} c Example error handling ierr = idba_presentati(dbhandle, "dsn", "user", "password") if (ierr.ne.0) then c handle the error... end if \end{verbatim} Or they can be handled by installing a callback function that is automatically called in case of error: \begin{verbatim} c How to set a callback c * the first parameter is the error code that triggers the callback (0 c means 'trigger on all errors') c * the second parameter is the routine to call when the error happens c (remember to declare the function as 'external' c * the third parameter is a convenience arbitrary integer that will be c passed to the function c * the fourth parameter is used to return a handle that can be used to c remove the callback ierr = idba_error_set_callback(0, error_handler, 42, cb_handle) \end{verbatim} The previous code will setup DB-ALLe to call {\tt error\_handler} after any error, passing it the integer value 42. The callback can be removed at any time by calling {\tt idba\_error\_remove\_callback}: \begin{verbatim} c How to remove a callback ierr = idba_error_remove_callback(cb_handle) \end{verbatim} This is a useful error handling function: \begin{verbatim} c The error handler needs to be declared 'external' external error_handler c Compute the length of a string c (this is an utility function that is used by the error handler c to print nicer error messages) integer function istrlen(string) character string*(*) istrlen = len(string) do while ((string(istrlen:istrlen).eq." " .or. $ string(istrlen:istrlen).eq."").and. $ istrlen.gt.0) istrlen = istrlen - 1 enddo return end c Generic error handler: print all available information c about the error, then exit subroutine error_handler(val) integer val character buf*1000 print *,ier," testcb in ",val call idba_error_message(buf) print *,buf(:istrlen(buf)) call idba_error_context(buf) print *,buf(:istrlen(buf)) call idba_error_details(buf) print *,buf(:istrlen(buf)) call exit (1) return end \end{verbatim} This code introduces three new functions: \begin{description} \item[{\tt idba\_error\_message}] returns a string describing what type of error has happened. \item[{\tt idba\_error\_context}] returns a string describing what \dballe{} was trying to do when the error happened. \item[{\tt idba\_error\_details}] returns a detailed description of the error, when available. If no detailed description is available, it returns an empty string. \end{description} A similar error handling behaviour can be obtained by using the predefined convenience function {\tt idba\_default\_error\_handler}: \label{fun-error-handler} \begin{verbatim} c Declare the external function (not necessary if you include dballeff.h) external idba_default_error_handler c Use it as the error handling callback ierr = idba_error_set_callback(0, idba_default_error_handler, 1, cb_handle) \end{verbatim} An alternative error handler called {\tt idba\_error\_handler\_tolerating\_overflows} is available: it exists on all errors instead of value overflows, in what case it prints a warning to standard error and allows the program to continue. The overflow error can then be catched, if needed, by inspecting the error code returned by the \dballe{} function that causes the error. This is how to use it: \begin{verbatim} c Declare the external function (not necessary if you include dballeff.h) external idba_error_handler_tolerating_overflows c Use it as the error handling callback ierr = idba_error_set_callback(0, idba_error_handler_tolerating_overflows, 1, cb_handle) \end{verbatim} \chapter {A working session} \label{ch-work} \section{Including the \dballe{} interface file} If you work using Fortran 90, \dballe{} comes with an interface file that you can use to enable type checking on all the \dballe{} API. To make use of the interface file, just include it at the beginning of your program: \begin{verbatim} include "dballe/dballeff.h" \end{verbatim} The Fortran 90 interface also allows to replace all the functions {\tt idba\_enqi}, {\tt idba\_enqr}, {\tt idba\_enqd} and {\tt idba\_enqc} with {\tt idba\_enq} and to replace all the functions {\tt idba\_seti}, {\tt idba\_setr}, {\tt idba\_setd} and {\tt idba\_setc} with {\tt idba\_set}. \section{Starting the work} Before any action routine, you need to connect to the database. Connecting to the database will give you a \emph{handle} that you can use to open sessions. This code will open a connection with \dballe{}, then it will start a session: \label{fun-idba_presentati} \label{fun-idba_preparati} \begin{verbatim} c Connect to the database and get a handle to work with it ierr = idba_presentati(dbhandle, "dsn", "username", "password") ierr = idba_preparati(dbhandle, handle, "read", "read", "read") c ...do your work... c End of the work ierr = idba_fatto(handle) call idba_arrivederci(dbhandle) \end{verbatim} You call {\tt idba\_presentati} to connect to the databse. The parameters are the usual ODBC triplet of DSN, username and password. There are alternative ways of invoking {\tt idba\_presentati}: see appendix \ref{dburls} for details. You can call {\tt idba\_preparati} many times and get more handles. This allows to perform many operations on the database at the same time. {\tt idba\_preparati} has three extra parameters that can be used to limit write operations on the database, as a limited protection against programming errors. The first extra parameter controls access to pseudoana records and can have these values: \begin{description} \item[{\tt "read"}] pseudoana records cannot be modified. \item[{\tt "write"}] pseudoana records can be added and removed. \end{description} The second extra parameter control access to observed data and can have these values: \begin{description} \item[{\tt "read"}] data cannot be modified in any way. \item[{\tt "add"}] data can be added to the database, but existing data cannot be modified. Deletions are disabled. This is used to insert new data in the database while preserving the data that was already present in it. \item[{\tt "write"}] data can freely be added, overwritten and deleted. \end{description} The third extra parameter controls access to data attributes and can have these values: \begin{description} \item[{\tt "read"}] attributes cannot be modified in any way. \item[{\tt "write"}] attributes can freely be added, overwritten and deleted. \end{description} Note that some combinations are illegal, such as pseudoana=read and data=add (when adding a new data, it's sometimes necessary to insert new pseudoana records), or data=rewrite and attr=read (when deleting data, their attributes are deleted as well). \section{Starting the work on a message} Instead of connecting to a database, you can use the \dballe{} API to read and write message reports in BUFR, CREX format, and read, but not write, messages in AOF format. To do that, use {\tt idba\_messaggi} instead of both {\tt idba\_presentati} and {\tt idba\_preparati}. To write a message, your code will look like: \begin{verbatim} c Connect to the database and get a handle to work with it ierr = idba_messaggi(handle, "file.bufr", "r", "auto") c ...do your work... c End of the work ierr = idba_fatto(handle) \end{verbatim} \label{fun-idba_messaggi} {\tt idba\_messaggi} has three parameters: \begin{enumerate} \item the name of the file to open \item the open mode ("r" for read, "w" for write or create, "a" for append). See the documentation of libc's {\tt fopen} for more details. \item the file format. It can be "BUFR", "CREX", "AOF" or "AUTO". "AUTO" tells \dballe{} to autodetect the file format, but it only works when reading files, not when writing new one. \end{enumerate} You can call {\tt idba\_messaggi} many times and read or write many files. You can even call {\tt idba\_messaggi} many time on the same file as long as you open it read only. Once you open a file, you can use the other \dballe{} functions on it. There are slight differences between working on a database and working on a file, and they are explained later in the section ``Working with files'' (see \ref{db-file-differences}). \section{Setting input and reading output} Input to action routines is done using the functions {\tt idba\_set*}, and output is read with the functions {\tt idba\_enq*} (see \ref{basics-inout}): \begin{verbatim} c Set the extremes of an area and retrieve all the stations in it ierr = idba_setd(handle, "latmin", 30.D0) ierr = idba_setd(handle, "latmax", 50.D0) ierr = idba_setd(handle, "lonmin", 10.D0) ierr = idba_setd(handle, "lonmax", 20.D0) ierr = idba_quantesono(handle, count) c Get the informations about a station do while (count.gt.0) ierr = idba_elencamele(handle) ierr = idba_enqc(handle, "name", cname) ierr = idba_enqi(handle, "ana_id", id) ierr = idba_enqd(handle, "lat", lat) ierr = idba_enqd(handle, "lon", lon) c .... count = count - 1 enddo \end{verbatim} Note that, when one uses {\tt idba\_setc}, {\tt idba\_seti}, {\tt idba\_enqc}, {\tt idba\_enqi} with parameters that have some decimal digits, \dballe{} will work with values as if they did not have a decimal point. That is, if latitude $10.124323$ is read with {\tt idba\_enqi}, then the result will be $10124323$. The following example shows exactly what happens: \begin{verbatim} c Set the latitude to 30.0 degrees ierr = idba_setr(handle, "lat", 30.0) c Set the latitude to 30.0 degrees ierr = idba_setd(handle, "lat", 30.0D0) c Set the latitude to 0.00030 degrees ierr = idba_seti(handle, "lat", 30) c Set the latitude to 30.0 degrees ierr = idba_seti(handle, "lat", 3000000) c Set the latitude to 0.00030 degrees ierr = idba_setc(handle, "lat", "30") c Set the latitude to 30.0 degrees ierr = idba_setc(handle, "lat", "3000000") \end{verbatim} \subsection {Parameter names} There are three different kinds of parameter names one can use: the \dballe{} parameters, the WMO B variables and the variable aliases. The \dballe{} parameters, fully described in \ref{parmtable}, are parameters that have a special meaning to \dballe{}: for example they can be part of the coordinate system, or space/time extremes to use to query the database. They are indicated simply with their name (for example, {\tt "lat"} or {\tt "yearmin"}). The WMO B variables, fully described in the WMO B table, represent all possible sorts of observed data, and are indicated in the form ``B{\itshape xxyyy}'', where {\itshape xxyyy} are the X and Y values from the WMO table B. For more details on working with observed data, see \ref{obsdata}. For a list of all the currently available B table descriptors, see \ref{btable}. The variable aliases are short, easy to remember names which can be used instead of frequently used WMO B variables. For a list of all the currently available aliases, see \ref{aliastable}. \subsection{Queries and observed data} \label{obsdata} The {\tt idba\_set*} and {\tt idba\_enq*} functions can also be used to set and get observation data. To do so, use as parameter the string {\tt "Bxxyyy"}, where {\tt xx} and {\tt yyy} are the X and Y values of the BUFR/CREX table B describing the observed data. For example: \begin{verbatim} c Set the speed of the wind (very useful in summer) ierr = idba_setr(handle, "B11002", 1.8) c Also set the temperature ierr = idba_setr(handle, "B12001", 21.8) ierr = idba_prendilo(handle) \end{verbatim} \subsection{Attributes} \label{sec-attrs} The {\tt idba\_set} and {\tt idba\_enq} groups of functions can also be used to set and get attributes on data. To do so, use as parameter the string {\tt "*Bxxyyy"}, where {\tt xx} and {\tt yyy} are the X and Y values of the BUFR/CREX table B describing the attribute. For example: \begin{verbatim} c Set the confidence of the wind speed value we inserted c in the last 'idba_prendilo' ierr = idba_setr(handle, "*B33007", 75.0) ierr = idba_setc(handle, "*var_related", "B11002") ierr = idba_critica(handle) \end{verbatim} \section {Querying the database} \ref{sec-querying} Queries are made by giving one or more extremes of space, time, level or time range. You can refer to section \ref{parmtable} for a list of all available query parameters (see the column ``On query input''). \subsection {Querying the anagraphical data} Example code to query all the stations in a given area: \label{fun-idba_quantesono} \label{fun-idba_elencamele} \begin{verbatim} ierr = idba_setd(handle, "latmin", 30.D0) ierr = idba_setd(handle, "latmax", 50.D0) ierr = idba_setd(handle, "lonmin", 10.D0) ierr = idba_setd(handle, "lonmax", 20.D0) ierr = idba_quantesono(handle, count) do while (count.gt.0) ierr = idba_elencamele(handle) ierr = idba_enqi(handle, "ana_id", id) c Pseudoana values can be read as well: ierr = idba_enqc(handle, "name", cname) ierr = idba_enqd(handle, "B07001", height) c ...query more data and work with it... count = count - 1 enddo \end{verbatim} This code introduces two new functions: \begin{description} \item[{\tt idba\_quantesono}] performs the query and returns the number of stations it finds. \item[{\tt idba\_elencamele}] gets a station out of the results of {\tt idba\_quantesono}. If there are no more stations, the function fails. \end{description} After {\tt idba\_elencamele}, the output record will also contain all the pseudoana values available for the station. If {\tt rep\_cod} or {\tt rep\_memo} are specified as query parameters, the pseudoana values of that network will be used. Else, {\tt idba\_elencamele} will use all available pseudoana values, choosing the one in the network with the highest priority in case the same pseudoana value is available on more than one network. \subsection {Querying the values} Example code to query all the values in a given area and time: \label{fun-idba_voglioquesto} \label{fun-idba_dammelo} \begin{verbatim} ierr = idba_seti(handle, "latmin", 30) ierr = idba_seti(handle, "latmax", 50) ierr = idba_seti(handle, "lonmin", 10) ierr = idba_seti(handle, "lonmax", 20) ierr = idba_seti(handle, "yearmin", 2004) ierr = idba_seti(handle, "yearmax", 2004) ierr = idba_voglioquesto(handle, count) do while (count.gt.0) ierr = idba_dammelo(handle, param) c get the value of this variable ierr = idba_enqc(handle, param, cvalue) ierr = idba_enqd(handle, "lat", dlat) ierr = idba_enqd(handle, "lon", dlon) c query more data and work with it count = count - 1 enddo \end{verbatim} This code introduces two new functions: \begin{description} \item[{\tt idba\_voglioquesto}] performs the query and returns the number of values it finds. \item[{\tt idba\_dammelo}] gets a value out of the result of {\tt idba\_voglioquesto}. If there are no more stations, the function fails. \end{description} \subsection {Clearing the database} You can initialise or reinitialise the database using {\tt idba\_scopa}: \label{fun-idba_scopa} \begin{verbatim} c Start the work with a clean database ierr = idba_scopa(handle, "repinfo.csv") \end{verbatim} {\tt idba\_scopa} clears the database if it exists, then recreates all the needed tables. Finally, it populates the informations about the reports (such as the available report types, their mnemonics and their priority) using the data in the file given as argument. The file is in CSV format, with 6 columns: \begin{enumerate} \item Report code (corresponding to parameter {\tt rep\_cod}) \item Mnemonic name (corresponding to parameter {\tt rep\_memo}) \item Report description \item Report priority (corresponding to parameter {\tt priority}) \item Ignored \item Ignored \end{enumerate} If {\tt ""} is given instead of the file name, {\tt idba\_scopa} will read the data from {\tt /etc/repinfo.csv}. This is an example of the contents of the file: \begin{verbatim} 01,synop,report synottico,100,oss,0 02,metar,metar,80,oss,0 03,temp,radiosondaggio,100,oss,2 04,ana_lm,valori analizzati LM,-1,ana,255 05,ana,analisi,-10,pre,255 06,pre_cleps_box1.5maxel001,previsti cosmo leps box 1.5 gradi valore max elemento 1,-1,pre,255 07,pre_lmn_box1.5med,previzione Lokal Model nudging box 1.5 gradi valore medio,-1,pre,255 08,pre_lmp_spnp0,previsione Lkal Model prognostica interpolato punto piu' vicino,-1,pre,255 09,boe,dati omdametrici,100,oss,31 \end{verbatim} {\tt idba\_scopa} will not work unless {\tt rewrite} has been enabled for the data when opening the database. \subsection {Inserting data} Data is inserted using {\tt idba\_prendilo}: \label{fun-idba_prendilo} \begin{verbatim} c Insert a new data in the database ierr = idba_setr(handle, "ana_id", 4) ierr = idba_setr(handle, "rep_memo", "synop") ierr = idba_setd(handle, "lat", 44.500D0) ierr = idba_setd(handle, "lon", 11.328D0) ierr = idba_setr(handle, "year", 2005) ierr = idba_setr(handle, "month", 7) ierr = idba_setr(handle, "day", 26) ... ierr = idba_setr(handle, "B11002", 1.8) ierr = idba_prendilo(handle) \end{verbatim} This code introduces a new function: \begin{description} \item[{\tt idba\_prendilo}] inserts a new value in the database. All the information about the parameter to insert is taken from the input previously set by {\tt idba\_set*} functions. When data of the same kind and with the same characteristics already exists, the behaviour of {\tt idba\_prendilo} is defined by the parameter passed to {\tt idba\_preparati} when creating the handle. See `Starting the work`\_ for more informations. \end{description} {\tt idba\_prendilo} will work in different ways according to the data opening mode of the database: \begin{description} \item[{\tt read}] causes an error, because the data cannot be read. \item[{\tt add}] new data can be inserted, but causes an error when trying to insert a value that already exists. \item[{\tt rewrite}] new data can be inserted, and existing data is overwritten. \end{description} Also, behaviour changes according to the pseudoana opening mode: \begin{description} \item[{\tt "reuse"}] when inserting data, if an existing pseudoana record for the data is found, it will be reused. \item[{\tt "rewrite"}] when inserting data, if an existing pseudoana record for the data is found, it will be completely overwritten with the parameters in input. \end{description} Note that the database cannot be opened in pseudoana {\tt read} mode when data is {\tt add} or {\tt rewrite}. \section{Deleting data} Data is deleted using {\tt idba\_dimenticami}: \label{fun-idba_dimenticami} \begin{verbatim} c Delete all data from the station with id 4 in year 2002 ierr = idba_seti(handle, "ana_id", 4) ierr = idba_seti(handle, "year", 2002) ierr = idba_dimenticami(handle) \end{verbatim} This code introduces a new function: \begin{description} \item[{\tt idba\_dimenticami}] deletes all the data found in the extremes specified in input. \end{description} {\tt idba\_dimenticami} will not work unless {\tt rewrite} has been enabled for the data when opening the database. \section {Attributes} \subsection{Reading attributes} Attributes are read using {\tt idba\_ancora}: \label{fun-idba_voglioancora} \label{fun-idba_ancora} \begin{verbatim} c ...setup a query... idba_voglioquesto(handle, count) do while (count.gt.0) ierr = idba_dammelo(handle, param) c Read QC informations about the last value read ierr = idba_voglioancora(handle, qc_count) do while (qc_count.gt.0) ierr = idba_ancora(handle, param) ierr = idba_enqc(handle, param, value) c ...process the value... qc_count = qc_count - 1 enddo count = count - 1 enddo \end{verbatim} This code introduces two new functions: \begin{description} \item[{\tt idba\_voglioancora}] Performs a query to retrieve attributes for the last variable read by {\tt idba\_dammelo}. It returns the number of attributes available. \item[{\tt idba\_ancora}] Retrieves one by one the values queried by {\tt idba\_voglioancora} if there are no more items available, the function will fail. The parameter {\tt param} will be set to the name (in the form {\tt *Bxxyyy}) of the attribute just read. \end{description} It is possible to read attributes at a later time giving a context ID and a B table value: \begin{verbatim} c Read the context ID after a prendilo or a dammelo idba_enqi(handle, "context_id", id) c ...a while later... c Query the attributes of the variable with the given c context ID and B table value idba_seti(handle, "*context_id", id) idba_seti(handle, "*var_related", "B12001") c These are ways one could choose specific attributes: c one attribute: idba_setc(handle, "*var", "B33007") c some attributes: idba_setc(handle, "*varlist", "B33007,B33036") c by default, all attributes are returned c Read QC informations about the last value read ierr = idba_voglioancora(handle, qc_count) do while (qc_count.gt.0) ierr = idba_ancora(handle, param) ierr = idba_enqc(handle, param, value) c ...process the value... qc_count = qc_count - 1 enddo \end{verbatim} \subsection{Writing attributes} \label{fun-idba_critica} Attributes are written using {\tt idba\_critica}, which can be used after an {\tt idba\_dammelo}, after an {\tt idba\_prendilo} or at any time using a stored data id. These three case differ on how to communicate to {\tt idba\_critica} what is the data about which to write attributes. When used after {\tt idba\_dammelo}, {\tt idba\_critica} can refer directly to the last data retrieved: \begin{verbatim} c ...setup a query... ierr = idba_voglioquesto(handle, count) do while (count.gt.0) ierr = idba_dammelo(handle, param) c ...process data... c Set the attributes ierr = idba_seti(handle, "*B33007", 75) ierr = idba_seti(handle, "*B33006", 42) ierr = idba_critica(handle) count = count - 1 enddo \end{verbatim} After an {\tt idba\_prendilo} instead, since {\tt idba\_prendilo} can write more than one data at a time, we need to tell {\tt idba\_critica} which of them we are referring to: \begin{verbatim} c Insert wind speed and temperature ierr = idba_setr(handle, "B11002", 1.8) ierr = idba_setr(handle, "B12001", 22) ierr = idba_prendilo(handle) c Set the attributes ierr = idba_seti(handle, "*B33007", 75) c Use "*var_related" to indicate which of the two variables we are annotating ierr = idba_setc(handle, "*var_related", "B11002") ierr = idba_critica(handle) \end{verbatim} {\tt idba\_critica} can also be called at any time using a previously stored data it: \begin{verbatim} c ...perform a query with idba\_voglioquesto... do while (count.gt.0) ierr = idba_dammelo(handle, param) c ...process data... c This variable is interesting: save the context ID c to refer to it later ierr = idba_enqi(handle, "context_id", saved_id) count = count - 1 enddo c ...some time later... c Insert attributes about that interesting variable ierr = idba_seti(handle, "*B33007", 75) ierr = idba_seti(handle, "*B33006", 42) c Select the variable using its context id c and variable code ierr = idba_seti(handle, "*context_id", saved_id) ierr = idba_seti(handle, "*var_related", "B11001") ierr = idba_critica(handle) \end{verbatim} This code introduces a new function: \begin{description} \item[{\tt idba\_critica}] Set one or more attributes about a variable. The variable can be identified directly by using {\tt idba\_seti(handle, "*context\_id", id)} and {\tt idba\_seti(handle, "*var\_related", name)}. These parameters are automatically set by the {\tt idba\_dammelo} and {\tt idba\_prendilo} action routines. The attributes and values are set as input to {\tt idba\_critica} using the {\tt idba\_set*} functions with an asterisk in front of the variable name. \end{description} {\tt idba\_critica} will work in different ways according to the attributes opening mode of the database: \begin{description} \item[{\tt "read"}] attributes cannot be modified in any way. \item[{\tt "rewrite"}] attributes can be added, and existing attributes can be overwritten. \end{description} \subsection{Deleting attributes} Attributes are deleted using {\tt idba\_scusa}: \label{fun-idba_scusa} \begin{verbatim} c Delete the confidence interval from the wind speed c The referring variable is identified in the same way as with c idba_critica: ierr = idba_seti(handle, "*context_id", saved_id) ierr = idba_seti(handle, "*var_related", "B11002") c The attributes to delete are selected by setting "*varlist": ierr = idba_setc(handle, "*varlist", "*B33007") ierr = idba_scusa(handle) \end{verbatim} This code introduces a new function: \begin{description} \item[{\tt idba\_scusa}] Delete attributes from a variable identified in the same way as with {\tt idba\_critica}. By default it deletes all attributes; specific attributes to delete can be selected by setting their names, separated by commas, in the "*varlist" variable. \end{description} {\tt idba\_scusa} will not work unless the database has been opened in attribute {\tt rewrite} mode. \section{Ending the work} When you are finished working with a handle, you can release it with {\tt idba\_fatto} \label{fun-idba_fatto} \begin{verbatim} c We are finished with this handle ierr = idba_fatto(handle) \end{verbatim} When you are finished working with DB-ALLe, you can ask it to close all connections and release all resources: \label{fun-idba_arrivederci} \begin{verbatim} c We do not need to work with dballe anymore call idba_arrivederci(dbh) \end{verbatim} \chapter{Advanced topics} \section{Shortcuts to stations and data} \dballe{} offers two shortcuts to represent pseudoana entries and data in the database: the {\tt ana\_id} and the {\tt data\_id} keys, that are set in the output of every {\tt idba\_dammelo}. {\tt ana\_id} represents a pseudoana entry. Every time one needs to specify a set of latitude, longitude, fixed/mobile, one could use the corresponding {\tt ana\_id} value, if known, and get a faster search. {\tt data\_id} represents a data entry. Every time one needs to identify some data setting latitude, longitude, level layer, time range and so on, one can just provide the value of {\tt data\_id}, and also get a faster search. \section{Helpers for pretty printing} \label{fun-pprint} There are a number of functions in \dballe{}, the {\tt idba\_spiega\*} group of functions, that are not needed for normal processing but can be useful to improve the presentation of data to users. All these function take a number of parameters and a string, and they store a proper description of the values into the string. The functions are: \begin{description} \item[{\tt idba\_spiegal(handle,ltype1,l1,ltype2,l2,string)}] Describes a level. For example, {\tt idba\_spiegal(handle,106,10,106,20,string)} will store in {\tt string} something like: ``\emph{Layer between 10hm and 20hm above ground}``. \item[{\tt idba\_spiegat(handle,ptype,p1,p2,string)}] Describes a time range. For example, {\tt idba\_spiegat(handle,3,0,600,string)} will store in {\tt string} something like: ``\emph{Average between reference time+0s to reference time+600s}``. \item[{\tt idba\_spiegab(handle,varcode,value,string)}] Describe a value. For example, {\tt idba\_spiegab(handle,"B12001","280",string)} will store in {\tt string} something like: ``\emph{280 (K) TEMPERATURE/DRY-BULB TEMPERATURE}``. \end{description} \section{Query modifiers} \dballe{} allows to set special query behaviours using the {\tt "query"} parameter. The available options are: \begin{description} \item [best] When measures from different kinds of reports exist in the same physical space, do not return them all, but only return the one of the record type with the highest priority. \item [bigana] Use special query optimizations that make things faster when there are a lot of stations in the database, and slower otherwise. If you are having slow queries, try setting this option and see if it helps. \item [nosort] Return the results in a nondefined order. It can make things faster when writing algorithms that do not depend on the ordering of data from \dballe{}. \item [stream] Normally the functions {\tt idba\_quantesono} or {\tt idba\_voglioquesto} will read all the results from the server, count them and save them locally. When using this option, those functions will return right after performing the query, and the results will be read later using {\tt idba\_elencamele} or {\tt idba\_dammelo}. As a side effect, {\tt idba\_quantesono} and {\tt idba\_voglioquesto} cannot know in advance the result count, and will return some undefined value in it. When using this option, the only way to find out when to stop reading is to know that {\tt idba\_elencamele} and {\tt idba\_dammelo} will set all the output parameters to undefined when there is no more data to read. One could thus use a loop like this: \begin{verbatim} ierr = idba_setc (handle, "query", "stream") c Make the query ierr = idba_voglioquesto (handle, N) c Iterate the results. Ignore N because it is c meaningless when using query=stream do ierr = idba_dammelo (handle, varname) c If ana_id is missing value, then we are done idba_enqi(handle, "ana_id", value) if (value .eq. 2147483647) exit c ...process the data... enddo \end{verbatim} This option can be a significant improvement in speed and memory when the result count is not needed in advance. The speed improvement comes because the client can start doing computations on the results while the server is still generating the results, taking advantage of parallelism, especially if the server and the application are on two different computers. Without using this option, the client cannot start to use the results until the server has finished computing and trasmitting them. \end{description} \section{Working with files} \label{db-file-differences} This is a list of the differences between working with files and working with databases: \begin{itemize} \item You do not need to call {\tt idba\_presentati} and {\tt idba\_arrivederci}: the work session starts at {\tt idba\_messaggi} and ends at {\tt idba\_fatto} \item When reading, performing {\tt idba\_quantesono} or {\tt idba\_voglioquesto} a second time advances to the next message in the file. \item Query parameters set before an {\tt idba\_voglioquesto} have no effect: filtering data is not implemented for files. Since it may be implemented in the future, it is suggested to avoid setting query parameters before an {\tt idba\_voglioquesto} to avoid unexpected changes of behaviour with future versions of \dballe{}. \item When reading, you will see that there are no more messages because {\tt idba\_quantesono} or {\tt idba\_voglioquesto} will return 0. \item When writing, you can use the {\tt query} input parameter to {\tt idba\_prendilo} to control when a new message is started. If you set it to {\tt subset}, then the data will be inserted in a new BUFR or CREX subset. If you set it to {\tt message}, you will start a new message. After ``message'' you can specify a template for the message, using one of the names listed by {\tt dbadb export -t list}, for example: ``{\tt message generic}''. If you do not specify a template name, an appropriate template will automatically be chosen for you. \item Setting {\tt rep\_memo} you can influence the output template of messages: if you set it to a synop report code, you will create a synop message. \end{itemize} \chapter{Code examples} \label{ch-examples} % TODO: put some more example code snippets from real-world \section{Insert station data, then insert data} \begin{verbatim} ierr = idba_preparati(dbhandle, handle, "write", "add", "write") c Insert data about a station ierr = idba_setr (handle, "lat", 11.345) ierr = idba_setr (handle, "lon", 44.678) ierr = idba_setr (handle, "height", 23) ierr = idba_prendilo (handle) c Read the station ID for the station we just inserted c Use *ana_id instead of ana_id after an idba_prendilo ierr = idba_enqi (handle, "*ana_id", anaid) c Reset the input data ierr = idba_unsetall (handle) c Add data to the station we just inserted ierr = idba_seti (handle, "ana_id", anaid) ierr = idba_setlevel (handle, 100, 1, 0, 0) ierr = idba_settimerange (handle, 0, 0, 0) ierr = idba_setdate (handle, 2006, 06, 20, 19, 30, 0) ierr = idba_seti (handle, "t", 21) ierr = idba_setc (handle, "B12345", "ciao") ierr = idba_prendilo (handle) \end{verbatim} \section{Query data, then query station data} \begin{verbatim} ierr = idba_preparati(dbhandle, handle, "read", "read", "read") ierr = idba_preparati(dbhandle, handleana, "read", "read", "read") c Prepare a query ierr = idba_setd (handle, "latmin", 10) ... ierr = idba_setd (handle, "lonmax", 60) c Make the query ierr = idba_voglioquesto (handle, N) c Iterate the results do i=1,N ierr = idba_dammelo (handle, varname) c Read data about the variable we just had ierr = idba_enqlevel (handle, ltype, l1, l2) c Read pseudoana data about the variable we just had c Setup a query for the station with 'quantesono' ierr = idba_enqi (handle, "ana_id", anaid) ierr = idba_seti (handleana, "ana_id", anaid) c Query. Nstaz should always be 1 because we query a specific station ierr = idba_quantesono (handleana, Nstaz) c Fetch the data ierr = idba_elencamele (handleana) c Read the data about the station c All the data inserted with setcontextana is available here ierr = idba_enqi (handleana, "height", height) enddo \end{verbatim} \chapter{FAQ and Troubleshooting} \label{ch-trouble} \begin{description} \item [ {\tt ierr = idba\_setc (handle, "query", "stream")} does not make any difference ] Because of a quirk of the MySQL ODBC driver, you may need to add a special configuration option to the MySQL driver. These are the instructions that you, or the person who set up ODBC in your computer, can follow: \begin{quote} You need to add 1048576 to the value of the Options field of the configuration of the ODBC DSN. This can be done by adding the line {\tt Option = 1048576} to the file {\tt odbc.ini}, or editing the Options field using the graphical ODBC configuration tool. \end{quote} \item [ How do I access the extra station data? ] There are two ways: \begin{enumerate} \item If you know in advances what variables you want to read, you can find them among the results of {\tt idba\_elencamele}: \begin{verbatim} c Query station data ierr = idba_quantesono(handle, count) c Get the informations about a station do i=1,count ierr = idba_elencamele(handle) ierr = idba_enqc(handle, "name", cname) ierr = idba_enqi(handle, "B02001", type) c .... enddo \end{verbatim} \item If you want to see all the extra station data available, you can make an explicit query for the extra station data using {\tt idba\_voglioquesto} and {\tt idba\_dammelo} \begin{verbatim} ierr = idba_seti("ana_id", id) ierr = idba_voglioquesto(handle, count) do i=1,count ierr = idba_dammelo(handle, param) c get the value of this variable ierr = idba_enqc(handle, param, cvalue) print*,param,": ",cvalue enddo \end{verbatim} \end{enumerate} \end{description} \appendix \chapter{Input and output parameters} \section{For data-related action routines} \label{parmtable} \input{../dballe/core/record_keyword.tex} \section{For attribute-related action routines} {\begin{scriptsize} \begin{longtable}{|@{\hspace{0.5mm}}l@{\hspace{0.5mm}}|@{\hspace{0.5mm}}l@{\hspace{0.5mm}}|@{\hspace{0.5mm}}l@{\hspace{0.5mm}}|@{\hspace{0.5mm}}p{2.0cm}@{\hspace{0.5mm}}|@{\hspace{0.5mm}}p{1.4cm}@{\hspace{0.5mm}}|@{\hspace{0.5mm}}p{1.4cm}@{\hspace{0.5mm}}|@{\hspace{0.5mm}}p{1.4cm}@{\hspace{0.5mm}}|@{\hspace{0.5mm}}p{3.5cm}@{\hspace{0.5mm}}|} \hline {\em Name} & {\em Unit} & {\em Format} & {\em Description} & {\em On insert input} & {\em On query input} & {\em On output} & {\em Comment} \\ \hline \endhead \hline \endfoot {\tt *Bxxyyy} & depends & depends & Value of the attribute & required & ignored & present & \\ {\tt *var} & Character & 7 chars & Attribute queried & ignored & optional & present, indicates the name of the last attribute returned & \\ {\tt *varlist} & Character & 255 chars & List of attributes to query & ignored & optional & absent & Comma-separated list of attribute B codes wanted on output \\ {\tt *var\_related} & Character & 6 chars & Variable related to the attribute to query & required & required & absent & It is automatically set by {\tt idba\_dammelo} and {\tt idba\_prendilo} (when {\tt idba\_prendilo} inserts a single variable) \\ {\tt *context\_id} & Numeric & 10 digits & Context ID of the variable related to the attribute to query & required & required & absent & It is automatically set by {\tt idba\_dammelo} and {\tt idba\_prendilo} \\ \hline \end{longtable} \end{scriptsize} } \chapter{Values for level/layer and time range} \section{Level/layer} \label{levels} \input{../dballe/msg/ltypes.tex} \section{Time range} \label{tranges} \input{../dballe/msg/tranges.tex} \chapter{Contents of the local B table} \section{B table contents} \label{btable} \input{../tables/dballe.tex} \section{Extra code tables} \label{extract} This section lists extra code tables defined by \dballe{} that define useful values to be used as attributes. \subsection{Code table 33196: \emph{Data has been invalidated}} This attribute is useful to mark when a value has been invalidated as a consequence of quality checks. \begin{tabular}{|l|l|} \hline {\em Value} & {\em Description} \\ \hline 0 & data has been checked and not invalidated \\ 1 & data has been not invalidated \\ missing & data has not beek checked \\ \hline \end{tabular} \subsection{Code table 33197 \emph{Manual replacement in substitution}} This attribute is useful to track when a value has been manually substitute, and it allows to identify both the original value and the new value that substituted it. \begin{tabular}{|l|l|} \hline {\em Value} & {\em Description} \\ \hline 0 & no substitution happened \\ 1 & substitution happened, and this is the original value \\ 2 & substitution happened, and this is the substituted value \\ missing & no substitution information \\ \hline \end{tabular} \chapter{Variable aliases} \label{aliastable} \input{../dballe/core/aliases.tex} \chapter{Database connection methods} \label{dburls} Instead of the usual DSN, user and password triplet it is possible to connect to the database using an URL-like syntax. \section{Connecting via ODBC} Specifying DSN, user and password: \begin{description} \item[in Fortran] {\tt ierr = idba\_presentati(dbhandle, "dsn", "username", "password")} \item[with dbadb] {\tt dbadb \-\-dsn=dsn \-\-user=username \-\-pass=password} \end{description} Via URL: \begin{description} \item[in Fortran] {\tt ierr = idba\_presentati(dbhandle, "odbc://username:password@dsn", DBA\_MVC, DBA\_MVC)} \item[with dbadb] {\tt dbadb \-\-dsn="odbc://username:password@dsn" \dots} \item[with provami] {\tt provami "odbc://username:password@dsn"} \end{description} Via an environment variable: \begin{verbatim} # Export the environment variable export DBA_DB="odbc://username:password@dsn" \end{verbatim} \begin{description} \item[in Fortran] {\tt ierr = idba\_presentati(dbhandle, DBA\_MVC, DBA\_MVC, DBA\_MVC)} \item[with dbadb] {\tt dbadb \dots} \item[with provami] {\tt provami} \end{description} \section{Using a SQLite file directly} Using SQLite makes \dballe{} very slow, but it is very useful when working with small datasets since it does not require any ODBC set up. For example, it can be used to run software to process small BUFR files: \begin{verbatim} export DBA_DB="sqlite:temp.sqlite" dbadb wipe dbadb import data.bufr # ...run something here that processes the data... dbadb export > processed-data.bufr rm temp.sqlite \end{verbatim} Via URL: \begin{description} \item[in Fortran] {\tt ierr = idba\_presentati(dbhandle, "sqlite:file.sqlite", DBA\_MVC, DBA\_MVC)} \item[with dbadb] {\tt dbadb \-\-dsn="sqlite:file.sqlite" \dots} \item[with provami] {\tt provami \-\-dsn="sqlite:file.sqlite"} \end{description} Via an environment variable: \begin{verbatim} # Export the environment variable export DBA_DB="sqlite:file.sqlite" \end{verbatim} \begin{description} \item[in Fortran] {\tt ierr = idba\_presentati(dbhandle, DBA\_MVC, DBA\_MVC, DBA\_MVC)} \item[with dbadb] {\tt dbadb \dots} \item[with provami] {\tt provami} \end{description} \chapter{Summary of routines} This appendix contains some reference tables for the functions in the Fortran API. \section{Input/Output routines} These routines are used to set the input and read the output of action routines. \begin{tabular}{|l|l|l|} \hline {\em Name} & {\em Description} & {\em See} \\ \hline {\tt \small idba\_seti(h, param, val)} & Set an integer in input & \ref{fun-idba_set} \\ {\tt \small idba\_setr(h, param, val)} & Set a real in input & \ref{fun-idba_set} \\ {\tt \small idba\_setd(h, param, val)} & Set a double in input & \ref{fun-idba_set} \\ {\tt \small idba\_setc(h, param, val)} & Set a character in input & \ref{fun-idba_set} \\ {\tt \small idba\_unset(h, param)} & Unset a value from the input & \ref{fun-idba_unset} \\ {\tt \small idba\_unsetall(h)} & Unset all values from the input & \ref{fun-idba_unsetall} \\ {\tt \small idba\_unsetb(h)} & Unset B* values from the input & \ref{fun-idba_unsetb} \\ {\tt \small idba\_enqi(h, param, val)} & Read an integer from the output & \ref{fun-idba_enq} \\ {\tt \small idba\_enqr(h, param, val)} & Read a real from the output & \ref{fun-idba_enq} \\ {\tt \small idba\_enqd(h, param, val)} & Read a double from the output & \ref{fun-idba_enq} \\ {\tt \small idba\_enqc(h, param, val)} & Read a character from the output & \ref{fun-idba_enq} \\ \hline \end{tabular} The following routines are shortcuts for combinations of the above ones. \begin{tabular}{|l|p{6cm}|l|} \hline {\em Name} & {\em Description} & {\em See} \\ \hline {\tt \small idba\_setcontextana(h)} & Set query parameters to the anagraphical context & \ref{fun-shortcuts} \\ {\tt \small idba\_enqlevel(h,type1,l1,type2,l2)} & Read level data & \ref{fun-shortcuts} \\ {\tt \small idba\_setlevel(h,type1,l1,type2,l2)} & Set level data & \ref{fun-shortcuts} \\ {\tt \small idba\_enqtimerange(h,type,p1,p2)} & Read time range data & \ref{fun-shortcuts} \\ {\tt \small idba\_settimerange(h,type,p1,p2)} & Set time range data & \ref{fun-shortcuts} \\ {\tt \small idba\_enqdate(h,y,m,d,h,m,s)} & Read date information & \ref{fun-shortcuts} \\ {\tt \small idba\_setdate(h,y,m,d,h,m,s)} & Set date information & \ref{fun-shortcuts} \\ {\tt \small idba\_setdatemin(h,y,m,d,h,m,s)} & Set minimum date for a query & \ref{fun-shortcuts} \\ {\tt \small idba\_setdatemax(h,y,m,d,h,m,s)} & Set maximum date for a query & \ref{fun-shortcuts} \\ \hline \end{tabular} \section{Session routines} These routines are used to begin and end working sessions with \dballe{}. \begin{tabular}{|l|l|l|} \hline {\em Name} & {\em Description} & {\em See} \\ \hline {\tt \small idba\_presentati(dbh,dsn,user,pwd)} & Connect to the database & \ref{fun-idba_presentati} \\ {\tt \small idba\_preparati(dbh,h,mana,mdata,mattr)} & Open a new session & \ref{fun-idba_preparati} \\ {\tt \small idba\_messaggi(h,filename,mode,type)} & Work with a message file & \ref{fun-idba_messaggi} \\ {\tt \small idba\_fatto(h)} & Close a session & \ref{fun-idba_fatto} \\ {\tt \small idba\_arrivederci(dbh)} & Disconnect from the database & \ref{fun-idba_arrivederci} \\ \hline \end{tabular} \section{Action routines} \begin{tabular}{|l|l|l|} \hline {\em Name} & {\em Description} & {\em See} \\ \hline {\tt \small idba\_scopa(h, filename)} & Reinitialise the database & \ref{fun-idba_scopa} \\ {\tt \small idba\_quantesono(h, count)} & Query the stations archive & \ref{fun-idba_quantesono} \\ {\tt \small idba\_elencamele(h)} & Fetch data about a station & \ref{fun-idba_elencamele} \\ {\tt \small idba\_voglioquesto(h, count)} & Query the data archive & \ref{fun-idba_voglioquesto} \\ {\tt \small idba\_dammelo(h, param)} & Fetch one observed data & \ref{fun-idba_dammelo} \\ {\tt \small idba\_prendilo(h)} & Insert values in the database & \ref{fun-idba_prendilo} \\ {\tt \small idba\_dimenticami(h)} & Remove values from the database & \ref{fun-idba_dimenticami} \\ {\tt \small idba\_voglioancora(h, count)} & Query QC data about a value & \ref{fun-idba_voglioancora} \\ {\tt \small idba\_ancora(h, param)} & Fetch QC data & \ref{fun-idba_ancora} \\ {\tt \small idba\_critica(h)} & Insert QC data about a value & \ref{fun-idba_critica} \\ {\tt \small idba\_scusa(h)} & Remove QC data & \ref{fun-idba_scusa} \\ \hline \end{tabular} \section{Pretty printing routines} \begin{tabular}{|l|l|l|} \hline {\em Name} & {\em Description} & {\em See} \\ \hline {\tt \small idba\_spiegal(handle,ltype1,l1,ltype2,l2,string)} & Describe a level layer & \ref{fun-pprint} \\ {\tt \small idba\_spiegat(handle,ptype,p1,p2,string)} & Describe a time range & \ref{fun-pprint} \\ {\tt \small idba\_spiegab(handle,varcode,value,string)} & Describe a value & \ref{fun-pprint} \\ \hline \end{tabular} \section{Error management routines} \begin{tabular}{|l|p{6cm}|l|} \hline {\em Name} & {\em Description} & {\em See} \\ \hline {\tt \small idba\_error\_code()} & Return the error code of the last function & \ref{fun-error} \\ {\tt \small idba\_error\_message(msg)} & Get the error message of the last function & \ref{fun-error} \\ {\tt \small idba\_error\_context(msg)} & Get the context description for the error of the last function & \ref{fun-error} \\ {\tt \small idba\_error\_details(msg)} & Get details about the error of the last function & \ref{fun-error} \\ {\tt \small idba\_error\_set\_callback(code,fun,data,h)} & Set a callback for handling errors & \ref{fun-error} \\ {\tt \small idba\_error\_remove\_callback(h)} & Remove a previously set callback & \ref{fun-error} \\ {\tt \small idba\_default\_error\_handler} & Predefined convenience error handler & \ref{fun-error-handler} \\ {\tt \small idba\_error\_handler\_tolerating\_overflows} & Predefined convenience error handler that does not exist on overflow errors & \ref{fun-error-handler} \\ \hline \end{tabular} \bibliography{local} \end{document} dballe-7.7/doc/Makefile.am0000644000175000017500000000544612652630043012346 00000000000000## Process this file with automake to produce Makefile.in guidesources = guide.tex intro.tex install.tex maintainance.tex troubleshooting.tex local.bib fapisources = fapi.tex ../dballe/core/record_keyword.tex ../dballe/msg/ltypes.tex ../dballe/msg/tranges.tex cdoxdeps = libdballe.dox \ ../dballe/libdballe.la \ ../dballe/msg/ltypes.dox \ ../dballe/msg/tranges.dox fortrandoxdeps = libdballef.dox \ ../fortran/libdballef.la LATEX2HTML = latex2html -local_icons doc_DATA = noinst_DATA = if DO_DOCS doc_DATA += libdballe.doxytags guide.pdf noinst_DATA += c_api/index.html if DO_DBALLEF doc_DATA += fapi.pdf libdballef.doxytags noinst_DATA += fortran_api/index.html endif if HAVE_LATEX2HTML noinst_DATA += \ fapi_html/index.html \ guide_html/index.html endif endif install-data-local: for pkg in c fortran; do \ test -d $${pkg}_api && \ $(mkinstalldirs) $(DESTDIR)$(docdir)/$${pkg}_api && \ find $${pkg}_api -type f -exec $(INSTALL_DATA) '{}' $(DESTDIR)$(docdir)/$${pkg}_api/ \; ; \ done || true for pkg in fapi_html guide_html; do \ test -d $$pkg && \ $(mkinstalldirs) $(DESTDIR)$(docdir)/$$pkg && \ find $$pkg -type f -exec $(INSTALL_DATA) '{}' $(DESTDIR)$(docdir)/$$pkg/ \; ; \ done || true uninstall-local: for pkg in c fortran; do \ rm -rf $(DESTDIR)$(docdir)/$${pkg}_api; \ done || true mainpages = ../dballe/main-core.dox #mainpages += ../dballe/main-bufrex.dox mainpages += ../dballe/main-msg.dox mainpages += ../dballe/main-db.dox TEXINPUTS="$(srcdir)" libwreport.doxytags: /usr/share/doc/libwreport-dev/libwreport.doxytags.gz zcat $< > $@ libdballe.doxytags c_api/index.html xml/index.xml: $(cdoxdeps) $(mainpages) doxygen $< libdballef.doxytags fortran_api/index.html: $(fortrandoxdeps) doxygen $< fapi_html/index.html: $(fapisources) $(LATEX2HTML) -dir fapi_html -split 1 -mkdir $< guide_html/index.html: $(guidesources) $(LATEX2HTML) -dir guide_html -split 1 -mkdir $< #fapi-quick.html: fapi-quick.rst ../dballe/core/dba_record_keyword.rst #fapi-quick.html: fapi-quick.rst # rst2html < $< > $@ %.ps: %.dvi TEXINPUTS="$(TEXINPUTS):" dvips $< -o %.pdf: %.tex pdflatex --shell-escape $< %.aux: %.tex TEXINPUTS="$(TEXINPUTS):" latex $< %.bbl: %.aux BIBINPUTS="$(TEXINPUTS):" bibtex `basename $< .aux` %.dvi: %.tex %.aux %.bbl TEXINPUTS="$(TEXINPUTS):" latex $< BIBINPUTS="$(TEXINPUTS):" bibtex `basename $< .tex` TEXINPUTS="$(TEXINPUTS):" latex $< # Additional dependencies for guide.dvi guide.dvi: $(guidesources) fapi.dvi: $(fapisources) EXTRA_DIST = $(guidesources) fapi.tex doxy2swig.py add_templates_to_manpage introduzione.odt CLEANFILES = libdballe.doxytags libdballef.doxytags {guide,fapi}.{ps,pdf,dvi,aux,bbl,idx,log,toc,blg} clean-local: rm -rf {c,fortran}_api rm -rf xml rm -rf guide_html rm -rf fapi_html rm -f libwreport.doxytags rm -f doxygen_sqlite3.db dballe-7.7/doc/doxy2swig.py0000755000175000017500000002727412652630043012631 00000000000000#!/usr/bin/env python """Doxygen XML to SWIG docstring converter. Converts Doxygen generated XML files into a file containing docstrings that can be used by SWIG-1.3.x. Note that you need to get SWIG version > 1.3.23 or use Robin Dunn's docstring patch to be able to use the resulting output. Usage: doxy2swig.py input.xml output.i input.xml is your doxygen generated XML file and output.i is where the output will be written (the file will be clobbered). """ # This code is implemented using Mark Pilgrim's code as a guideline: # http://www.faqs.org/docs/diveintopython/kgp_divein.html # # Author: Prabhu Ramachandran # License: BSD style from xml.dom import minidom import re import textwrap import sys import types import os.path def my_open_read(source): if hasattr(source, "read"): return source else: return open(source) def my_open_write(dest): if hasattr(dest, "write"): return dest else: return open(dest, 'w') class Doxy2SWIG: """Converts Doxygen generated XML files into a file containing docstrings that can be used by SWIG-1.3.x that have support for feature("docstring"). Once the data is parsed it is stored in self.pieces. """ def __init__(self, src): """Initialize the instance given a source object (file or filename). """ f = my_open_read(src) self.my_dir = os.path.dirname(f.name) self.xmldoc = minidom.parse(f).documentElement f.close() self.pieces = [] self.pieces.append('\n// File: %s\n'%\ os.path.basename(f.name)) self.space_re = re.compile(r'\s+') self.lead_spc = re.compile(r'^(%feature\S+\s+\S+\s*?)"\s+(\S)') self.multi = 0 self.ignores = ('inheritancegraph', 'param', 'listofallmembers', 'innerclass', 'name', 'declname', 'incdepgraph', 'invincdepgraph', 'programlisting', 'type', 'references', 'referencedby', 'location', 'collaborationgraph', 'reimplements', 'reimplementedby', 'derivedcompoundref', 'basecompoundref') #self.generics = [] def generate(self): """Parses the file set in the initialization. The resulting data is stored in `self.pieces`. """ self.parse(self.xmldoc) def parse(self, node): """Parse a given node. This function in turn calls the `parse_` functions which handle the respective nodes. """ pm = getattr(self, "parse_%s"%node.__class__.__name__) pm(node) def parse_Document(self, node): self.parse(node.documentElement) def parse_Text(self, node): txt = node.data txt = txt.replace('\\', r'\\\\') txt = txt.replace('"', r'\"') # ignore pure whitespace m = self.space_re.match(txt) if m and len(m.group()) == len(txt): pass else: self.add_text(textwrap.fill(txt)) def parse_Element(self, node): """Parse an `ELEMENT_NODE`. This calls specific `do_` handers for different elements. If no handler is available the `generic_parse` method is called. All tagNames specified in `self.ignores` are simply ignored. """ name = node.tagName ignores = self.ignores if name in ignores: return attr = "do_%s" % name if hasattr(self, attr): handlerMethod = getattr(self, attr) handlerMethod(node) else: self.generic_parse(node) #if name not in self.generics: self.generics.append(name) def add_text(self, value): """Adds text corresponding to `value` into `self.pieces`.""" if type(value) in (types.ListType, types.TupleType): self.pieces.extend(value) else: self.pieces.append(value) def get_specific_nodes(self, node, names): """Given a node and a sequence of strings in `names`, return a dictionary containing the names as keys and child `ELEMENT_NODEs`, that have a `tagName` equal to the name. """ nodes = [(x.tagName, x) for x in node.childNodes \ if x.nodeType == x.ELEMENT_NODE and \ x.tagName in names] return dict(nodes) def generic_parse(self, node, pad=0): """A Generic parser for arbitrary tags in a node. Parameters: - node: A node in the DOM. - pad: `int` (default: 0) If 0 the node data is not padded with newlines. If 1 it appends a newline after parsing the childNodes. If 2 it pads before and after the nodes are processed. Defaults to 0. """ npiece = 0 if pad: npiece = len(self.pieces) if pad == 2: self.add_text('\n') for n in node.childNodes: self.parse(n) if pad: if len(self.pieces) > npiece: self.add_text('\n') def space_parse(self, node): self.add_text(' ') self.generic_parse(node) do_ref = space_parse do_emphasis = space_parse do_bold = space_parse do_computeroutput = space_parse do_formula = space_parse def do_compoundname(self, node): self.add_text('\n\n') data = node.firstChild.data self.add_text('%%feature("docstring") %s "\n'%data) def do_compounddef(self, node): kind = node.attributes['kind'].value if kind in ('class', 'struct'): prot = node.attributes['prot'].value if prot <> 'public': return names = ('compoundname', 'briefdescription', 'detaileddescription', 'includes') first = self.get_specific_nodes(node, names) for n in names: if first.has_key(n): self.parse(first[n]) self.add_text(['";','\n']) for n in node.childNodes: if n not in first.values(): self.parse(n) elif kind in ('file', 'namespace'): nodes = node.getElementsByTagName('sectiondef') for n in nodes: self.parse(n) def do_includes(self, node): self.add_text('C++ includes: ') self.generic_parse(node, pad=1) def do_parameterlist(self, node): self.add_text(['\n', '\n', 'Parameters:', '\n']) self.generic_parse(node, pad=1) def do_para(self, node): self.add_text('\n') self.generic_parse(node, pad=1) def do_parametername(self, node): self.add_text('\n') self.add_text("%s: "%node.firstChild.data) def do_parameterdefinition(self, node): self.generic_parse(node, pad=1) def do_detaileddescription(self, node): self.generic_parse(node, pad=1) def do_briefdescription(self, node): self.generic_parse(node, pad=1) def do_memberdef(self, node): prot = node.attributes['prot'].value id = node.attributes['id'].value kind = node.attributes['kind'].value tmp = node.parentNode.parentNode.parentNode compdef = tmp.getElementsByTagName('compounddef')[0] cdef_kind = compdef.attributes['kind'].value if prot == 'public': first = self.get_specific_nodes(node, ('definition', 'name')) name = first['name'].firstChild.data if name[:8] == 'operator': # Don't handle operators yet. return defn = first['definition'].firstChild.data self.add_text('\n') self.add_text('%feature("docstring") ') anc = node.parentNode.parentNode if cdef_kind in ('file', 'namespace'): ns_node = anc.getElementsByTagName('innernamespace') if not ns_node and cdef_kind == 'namespace': ns_node = anc.getElementsByTagName('compoundname') if ns_node: ns = ns_node[0].firstChild.data self.add_text(' %s::%s "\n%s'%(ns, name, defn)) else: self.add_text(' %s "\n%s'%(name, defn)) elif cdef_kind in ('class', 'struct'): # Get the full function name. anc_node = anc.getElementsByTagName('compoundname') cname = anc_node[0].firstChild.data self.add_text(' %s::%s "\n%s'%(cname, name, defn)) for n in node.childNodes: if n not in first.values(): self.parse(n) self.add_text(['";', '\n']) def do_definition(self, node): data = node.firstChild.data self.add_text('%s "\n%s'%(data, data)) def do_sectiondef(self, node): kind = node.attributes['kind'].value if kind in ('public-func', 'func'): self.generic_parse(node) def do_simplesect(self, node): kind = node.attributes['kind'].value if kind in ('date', 'rcs', 'version'): pass elif kind == 'warning': self.add_text(['\n', 'WARNING: ']) self.generic_parse(node) elif kind == 'see': self.add_text('\n') self.add_text('See: ') self.generic_parse(node) else: self.generic_parse(node) def do_argsstring(self, node): self.generic_parse(node, pad=1) def do_member(self, node): kind = node.attributes['kind'].value refid = node.attributes['refid'].value if kind == 'function' and refid[:9] == 'namespace': self.generic_parse(node) def do_doxygenindex(self, node): self.multi = 1 comps = node.getElementsByTagName('compound') for c in comps: refid = c.attributes['refid'].value fname = refid + '.xml' if not os.path.exists(fname): fname = os.path.join(self.my_dir, fname) print "parsing file: %s"%fname p = Doxy2SWIG(fname) p.generate() self.pieces.extend(self.clean_pieces(p.pieces)) def write(self, fname): o = my_open_write(fname) if self.multi: o.write("".join(self.pieces)) else: o.write("".join(self.clean_pieces(self.pieces))) o.close() def clean_pieces(self, pieces): """Cleans the list of strings given as `pieces`. It replaces multiple newlines by a maximum of 2 and returns a new list. It also wraps the paragraphs nicely. """ ret = [] count = 0 for i in pieces: if i == '\n': count = count + 1 else: if i == '";': if count: ret.append('\n') elif count > 2: ret.append('\n\n') elif count: ret.append('\n'*count) count = 0 ret.append(i) _data = "".join(ret) ret = [] for i in _data.split('\n\n'): if i == 'Parameters:': ret.extend(['Parameters:', '\n\n']) elif i.find('// File:') > -1: # leave comments alone. ret.extend([i, '\n']) else: _tmp = textwrap.fill(i.strip()) _tmp = self.lead_spc.sub(r'\1"\2', _tmp) ret.extend([_tmp, '\n\n']) return ret def main(input, output): p = Doxy2SWIG(input) p.generate() p.write(output) if __name__ == '__main__': if len(sys.argv) != 3: print __doc__ sys.exit(1) main(sys.argv[1], sys.argv[2]) dballe-7.7/doc/introduzione.odt0000644000175000017500000004013712652630043013547 00000000000000PKŠä4^Æ2 ''mimetypeapplication/vnd.oasis.opendocument.textPKŠä4Configurations2/statusbar/PKŠä4'Configurations2/accelerator/current.xmlPKPKŠä4Configurations2/floater/PKŠä4Configurations2/popupmenu/PKŠä4Configurations2/progressbar/PKŠä4Configurations2/menubar/PKŠä4Configurations2/toolbar/PKŠä4Configurations2/images/Bitmaps/PKŠä4 content.xmlí]KoIr¾ûW$hxA.Øï'©#+@£¥‡ZïÞ„dUv3­êÊRVUSÒiþO¶/k`à“>ÍÍWëŸÌðopDdf=úÅêf7»9àb1bWå#"2_DfU}ó‡O“€M…Ž¥ ŸµêÍ#&BOù2??úó»ïkã?\üÝ7j4’ž8÷•—ND˜Ô<&ð/ƒÞa|nî>?Jux®x,ãóOD|žxç*¡ëu^l}Ns™+qò9¨Ü{'âSRµ3¶-õå×Õg¦ÆÅÞ¾æ·U;c[j±ûHUíü)j#RŸD<‘3T| døáùÑM’DçÆíímý¶SWzÜh5ènF°—µ‹RP+ßkˆ@àdq£Uo5\Û‰HxUú°m‘¤0\ ]Y4<ás«OÇ•5b:^"ï†ëʺAËËÛñ«/oÇ/öðäfÉš ?ÀMúÏor]ГªsaÛ’¨<-£ÊlšÖÅþJ©ŒTì` ”Èm7›Ý†ù]h}»²ù­–‰Ð…æÞÊæ¼Lâj²HhЮՀ51E5Í/éÐn˜ÛYãØ_:ô_xså݈ ÏË»×d'u|+ãø®©ËôÏ^çi$Ò«Ñ8™bÒK„^¶²¹,‰×|¬ytãnÀ ô£f%Á÷}»ùþZùŸÜàYÇZ¤Á=èD‚ÔG ¨˰–¨èùQÓ›®]«$AGá.cP¯ñ@ŽÁòÀ"uâhøç4Näès-†À TÜ* >`ă؈£ÀÝ VÛ;gu·ôw6¡ÿ‚#DZkÑïÁHèü·È@÷Þ `›2.7zÓ~×þr¶:¹»]0é`7“vWN:Üͤ½•“ž=”¯Ä(AìÓîµÊ–¢åø&™1ú0§½h†ÇøS+Ý\W“ZÍ߯¦Ý+L]í‹qÌRz°èm¤ÔÜ—6ì>tï–Ï 5g£Û·ÂB"4 Í­d‹<\Õóê@|Êš¬!ý€Ç¥˜¶ñ$>®®ÆØdUž7Â*÷çyo¶*¹¿+X½{v·Ö #èñ8ã…M"oˆå¸ØjEIÉìñ²ó ‹ofn¯!ëW5Û_€ÞÍ…»¤¨p³‚;çùn.rU"Ù®i—­¥µnϬõ<Î(Ã’þ›‹`.|ViJ ’Ï‘X*¥í!¨wsn~ç´†Zιû•jùH˜š‹w,æU¢•)¼šD7Xoì˜óÌë-ëEÚ»Ë}‰…7X¥Êb*·h´ÅÌM¼㻹á^Í@‘çG¿… \Sÿ Fr~ w|ijÿˆ::ÖE«(Xƒ¾öÓ×9púºN_ïÀéë8}ƒ§oxàô8}yïa ,Ü®sÚKcÎuà›9ô³ˆ$^P3Df7.²§£‘„`X·͘´·ûüèןþ³Š8âwù®1Ý&A ºCL)gDu+}<¬PHŸ+þÂöóráº×T{ÿ’jÕÏÎz‡/©Îþ%Õ©·»í×Twÿ’êֻó×Toÿ’êÕþáKª¿IõëgÃÎáKj°I ëíG ¨áþuVïH8Û¿¤Z€§Ú% šÞ»¬Q ö‡Öö=ûÿ—M€}¿³RÍí}+âvýÿýë/›ûöàðµe\ÿo?o”5Jm×ob|íz¯{ø‚Ú.¬ßÈö:õÖà¨Ô–aý&Æ×©SÁêÀµeT¿‰íANÝ}*µ]X¿‘ñõêÍ•¨þ0µeT¿‰íõêƒÖ#P©mƒúM¬¯_ß#ê\ÒwŸ ý¤‚ô@¥ž ý¤‚ôOþ°%õéŸ ý¤ß+¤ï=Aú'HÿéJ=Aú'HÿéŸ ýaKê Ò?Aú'H¿WHß_ó)®9Ù¾¥föÍE«Å›_t´v‰é·ølØÞ¹®ŒÏ·øÀÙ0]koñ1¶½s]7oñÙ¸½3]oñ‰»àº"žÝâc|{gº:6ÝâÃ{çº2ÎÜâ‡ÀtU̸Íç÷Îveü·öÑ¥ï µ7ð¥-Ùìne—hî}>¢ÚpŒíéªùå×´Kz¥ÿüÈKzÃá°Ûë7:”aŒüª0Üô­Ép¤.¾ñ½sO ž(}qå©PÅž ¿i®cŸ'â¢ÝlökÍA­Ù}מ7›ðjH73KÃ7fih, ¿OÃfÆ“¯ÙKDÁͼ®^êp§J“@†¢–ÁÑ‹w7"ŒkÁ’Á&\† Óî% æ1¨EÌÔˆY)Ý8qåün*¾³ÎY·»{•h=¤Jœu <íL%ª°DDó*q .H[þ¢-.f¯ÓkÿÖ³×=ëübòÐßÁr¶šÝáom9ÛÃîîÝõ}—ÓÜŒøU†/Úúêž5›öpç’hßS;a¼×;|Åé.…f±˜DuÌ€³ê$¿NúvʤQER©‰˜(-¿|Á žšö1åa"“¯?³‘Œqé@Ǥ §»§šFKCÎ̹d ˜ á‚bq$<œY‘ž+P$À«<õ›D88`¨4(eÜØŽCk„êÛ’ÉÎ4À˜b&Üø&‰Ÿv‚i¯XNN”Z'Éþòß؋?ÿ#ýòÇWeÇôÁL ×浜Šðn¥‰ HT@´œ Ñvxჭ~“¨Á & vl?uÆ`.öêåùž@p=Ù)ÓÀ,¬Ó¨ˆ½¥<Y'°ÂŸN?Ÿ~9Eµä8 ø_6vš/ò©qcÐÖðCòP|tcc¡ÆšŒÆ|A½Ënrü*+¸n…6€X‚[7¨h>-“QVÕÛ˜ºyã¯æP\ó»Š)^7.@å ?:© baÖO£`sWM?œ  Pqë>c‡"òÅH†Ò¬NÊ©òðZÀðs ´Z0Býi’ £•}ý…ñ)…$Ñò:%3ÙD êt¢‘Á  cŽ‹N¶ÇQSAæR•ÛÅi€ h ß1j®oMCÿ²0qÂÄA6˜ ChH3d€˜b«ÁõgÕ5ƒŠð‹DFqÈãUÔÛPqpJžb ^µ‚ÎP¼Q9TšÂrãBT$Ë6Ïw¤*Du^èC§ù$«#øŽrð6‘ {ÒüP (:QßÒjÿ“B±ä¨ÒøÑ$I5§  4ãÏ­)×+óKx Õ*N‘&¬` FbŒf˜@§.*»LPa|=‘a®D¦?S…~:Ç@¸YgE… epºß$…IòŠÂ46±ÎOx„b0Æûå_ˆ*,4¡3!¹0𢣠w¹5©]–q&¤f Âk~ÄzŒª"ÑÁLS4Žq耲ùTî–IJTò¿¨D][ļk BA9 7…ˆj¼ªD­ £@œYâ|ŽRºÓhí–¤ Bµì óÞ²A¢SææJšÈð©Òˆ"¾¶@ÒE§Üh4pµªßVÐ_X`½A»@äS•¯ªH÷4ÀÝQ/BwèÄQO Ê„€((-šÂßì­H<Ä k*çfÛÊ™ÊÙ0Ä]öíåë»S˹L}eùqÀ¹M?ÑQ(ëù¬Æ ÕäBПp‹%F~ÃqÅHe·L@®‘‚pX)\e}òªòÈ]Büš7ù]Eö ÉI’/µ©¼$÷Iºé¨|–1:•"ÇLf}aŠBKÃÕ¶É!|ôå)Þ¦¥07{A~ÔJR„ûðWŽá´ñÒ¸¨WŒá¶ùŒ‚Ý[ ø3šýÊ FƱƒ³±‡å{똋 )¥›C•„#!›#Ï&-Å,“Vªp$}Šg0â-· %Ròñ«knU•mÖ|Û²Ísœs¦2äM’-)!«{ŒBü„ù¸þÏ0e*„ ß%Úfˆƒóâ—!:ë!úG˜ä‘fH˜Y@|²à…V%‹îèчcIŠ(·É¾ {àĶŠ€È Ï—g[šäËùÒQ[œ*YÒnHÛÔmXØl-K+œ@Г6Ž8Ï"Šø²kK ¸¬˜ø °nš&”¾)<€ïB}<%PDŽÞUáš…C 4 …¶·Ú²<øsvP ñ)3é;È=•eo# †OˆÜ©ÛŠ X^:I¢~"|‰] Jg‰_ܸ8˜r‰ü¹¥Ç²™çƒ°ò‚Ÿ:4uç$<åKècÉrÜÀZ ð© Ï çãÅ=ÑÔz.RscÚÁÑdVlúS )<äÆh!„¸õͯaK‘„OËÃ} JsPØØŽIu%Ð"„œ%·€["àš(!2)l‚—µô!EÅÖ¥‚cŽ3SØÐDu4÷ªñÆlÎ7.Ê$T >®o¡ˆVyZÚ?pU­µ¯‡iFÎÌ•Ü[§("$0ŠU"ƒ³õ“Fš<—#FfúPVÒÑù~«9!7ð.–‚þŒ8¡/š·ì›ýéo8ú¯?ýX¬)‘”Â¥k•YMrÛÁÞÕ „gÙû©ÅÐÅ¢ÆO“Ç*Bçì0è©Ps™J‚I ‚â§37±&“]ÉËy*«éTZOgP³aŒd•åa>„0“i¢“ƒ"XzT+ ?Áý[Na=V£äÖØ¶331›ûl¸“X)?‚”Ô›Ù&ò…M“Ü&Ééާaé ègp?°Ë1„Qdu×Yƒ£ Üp…JZ›-GРã(|Ë}õ±“NŽ*óu®“ìß—#áè<ŒqèÖF XF¦*yF“›?©ú &›Šòù²U#CÈf»#Ö[E,èŠZ½ŠZ4‚ýSÛÏ©õWQë«ôüÍÎém5WEìËÖ]‡9{sFfY¢Ï„»åIHÃk¥>L¸þP<Í:Jà O„ï:¾tíʆaö÷á~Nì#°áµÈ†Úðávf„An‡t޶”'jJéP+ÆédQ¾XeÖl_‰³O€>œãyÙçG4£@Ùk7ZŒžÝ$ItÞhÄ‘ Ufà:â¼_>6@–{Õ' _y5<7Ù0üzõ›dü=Ç'ÖHêi¾ÓÒÇ/رÛ0v ALœÌ&¼‡ÀA§Èt(0aˆ?©Bt·b%mÉé| ⥠Cs’ °aœýehpÏPVª¡]ji¶-ÍVy9yÃE´Ù`ñ²íNòwWoÙñwX̽R©†pñF>aÊ¿ölF§5•ý|ëÙ—Ÿ|Ž?6#)[LEØXãáµì_3{LÓTÑÉ*sT¥Îr°-&žæ´±ƒR‹üœ,¶Y ›u ”+Mžg½*?ÉöŠö€HLâ01BxJ®Pzt OóPØB¯p"§D~V@ÔÓ­¶IýhrªíZ’DiXÏë3n:§cÝÊq¹DrB#pVO~ý…ö®°Ï8E’*ù‘ÞjÞÖcad:Nô€¢ýë²ëõãÐ9^óoãé‰(_ ¾UÚ7¿ªXÜÙ è`Jó—é€%ðËS®ºR‘€:ýo]bi e ßRêÌ5–¢|¡=y¼2b Ž.œ,=³zÂ{ï ,ª"­›‘¿´û…X&ב߬Xýï¯S7maùn¬P6bÇO¨sZÜ–S•mfè &Þ…uݼpŠ$µë­Ûs®ô$ŸÑ³R%ùÞ{ÊqPغºg±µ¼¢è”²Zª«à‰À†6»–1xHNûn…Cø¸Ù,‚ Ô¸õŒÝ1\gáÚ̸ÌL°S°TsæÙÏi˜#î Sö<†IßKÿ„¶Ù=ýïbwFÛÚ q <î—Ùìx¦3¬}sˆ1ó‰V0ôL¸€)7å´½)§FÈ rK…åÀf1Ô–ž ˱°c¸^M:£–¹ðn±z§”D8Ο½“ì÷9Å@ðï÷Zà3Ws²Û„_es‹ùÍ€Åqaݰv•? š lUØÁj¯U/|(5 Íœç,ZôðfM‹„ÛÌcªÝ~£\¿ð+y—4æU ¢æä-,r‰Üf©º=Ô‚²mó©ÝЦvνf©Ýèkw+qy­qGMK·É]ú’Õyl§%°{ æQ= àåÌÚn¼H6IÿߟrQ\ÁŽRh+Êî·§Ò0Ùt¹öÃgÏÕ£âñÆì Ó<Ÿ' HÛº*®l¿s™i1†‚”™çZ×cRÍNA®Óá‘Ù³[ö›¸mK¾ÒÎÀf5q¬?( °ä‘Ëq}Éþ·‰Ûø¨>w–=³€;yÂ/PU!ŠA¸‰úõgÞ˜O¸©d̤9|”¡@a¶_—®Ã©Y€‰ñy¡Ý¿Ð6*V^\T§÷ ·‘LíÍ|sÃ=܉²y 9‡ræâÉúaäìak³®¦oìÓœ©-Ø‚³^HûÀÒîó 8ÿUdçTÙR¿Ðs•òíúëE)þnÜqœ^Ó‘©Eÿvüðò¼ÀÅËÂùp±ñFÅ^:h^82‰Ñ7?éÃR%s¤ÅX™ÒÚTŽ•vÇ>ó½Ç+E)…}ˆf&ðKçUÉyê`pøþ¬13ÄÕÙë¹0ÜÊ*m®iB§êqj,ÓÛ.èˆ^æ¸U Ì[i H.*]/˜Á„";Ï‚ûY†b^·^?·Ò…xhßœSز5Ýï~&̼€³xϱÄÊlÝæùIiĥό¹ñîé-ÄK´]LÐñJÐW‹Xpó¬Â1‘ªáz隊h´êÒš÷–—¶tä7/Åç´Î±ƒdF¦ÓÜÙÃÁ;ٱ܇I~Î\òc ˆ`yõë-y&ó©jÊôŽÖÒz—Niïå®—ë.¸›þ~7;÷ëßÙ’oï_ÈkÀh”2ñu£ü÷æ©åìMr´qÅCJ–Ì#öqGzDÌœäÉ6)Ã‚Ä Ôfæ…\¥Ï¹_æKEîH;Å)kæ WÉÅÿPK¡7DÁ'ÅPKŠä4 styles.xmlÍ[[¯Û¸~ï¯0T´o²%;Ù»9Y´A/²‹¢9íë‚–h‹]‰(êØÞ_ßR”(Y’eûìÆybÎ…Ão†3CRùðý1Kg¯TLðg/œÞŒòHČÿ¼üÝò¾ÿø»b·cÝÄ"*3Ê•_¨SJ‹óbcˆÏ^)ùF‚N2ZlT´9åVhãroôTfD+›*®™]iEjª0ò¶dÉvúÌšÙ•Ž%9LF^ÀÔ߉©ÂÇ"õwÂD–Å:VSÆ~ö¥òÍbq8æ‡Õ\Èý"\¯× M­ Žj¾¼”©æŠ£M)NV,Ây¸°¼Udª}ÈëšÄËlKådhˆ"g^-^÷“#âu?M”9964sÛ½«xº{W±+›• øäiñõ_?|ibAfSçBÞT‘dùäenW^Q›Šfƒjs—Aðna~;܇QöƒdŠJ‡=eHÕˆ‹¬4à ÀáÓW SoV¥VÚúhsÔN@~Ú‘ˆú1Òâã[õðÌüFŒž½¯ŠÈ¯§l+Roqd¹2–ž:ÄF JAð£_êb|’O¢”ŒÊÙôÐ3ËI.Š?;7Ûñá©‹+ŠKS/†â¯7%ÓšÓ)ÓªZÍ•A{Iò„Ežå­~û¹„ $à°œlŠ„Äâàƒ~GÿøìóU”y}ÄS‡‘­|( Ô/rAaò!Ù/`:I‘uù4ÊüŠfDç¬m¦j=cíÑYÁ’Â:L%¾)õ;’޳s"‰FÈÅÇß'¥8D‹©0¬$Í“:ε[I ”ÑBÇ•¥`.CÛp¿={©ôÕ¶ŒÇS,¶Dîb¬‘ÖFhÀÓ"/0N†Í®ÙÑî³Õ”8zÕä!‘ (²J–œwÂXT°_ÀÒp™+=–¾/É×n"Qr%!>¿´V‚r>­t…M¥ÀÒXM©4YBŸ>¬Ê)=h¬©ç:khm kí™)©ÆØ €%9å åÐAî§$†ìêk[ž=.À³YcâĘÊK©Ò(<ê¬BãrÐÙ`ñc[ã$á|ù>lvD;,s³Ù7ÄŽã¶$~ot¡Z(=5æ­ƒOOWÇÐЄonðP»í»%iF׃ «åS^I‡åŽÐׇ7ÿ¤Ô s–Ù ‰‘Žaib"%y1zïľ‡Îä0ÒÙs?SšûJì©Jð°€{êÒÄî„uÇc"copë[祤(À<ØÍf9×÷ôŸ–ÁO[Ÿ¬(ìÃ<%'¿á˜¹äÁ)a >+ûýæºV]ÊQ‘@1H&&ƒfl+”ÂÞ*g¸RãøþIIì$¥{–Â1ñ¸ }PÞ¼Þù»åj|ÍuHéVëV¤r*.%G'óU½`'ß½kòÃÕé¬WöŠÜ„ò׺Qû£·â˜…·¸¼-W{ÜZTmmQ*]S8×Aþ ½!7uܾÿCã¢eû\ ç°xØ ZÄ!)Kî—m|0 ]3hù[œ´wÒòñœ´œê¤wU`ÆPK)Iá\s¥ïº;È,¦n ŒÊ›}ۯݩþCúï÷þjÜû«Çóþê&ïßææûÜxŸ“¾@ç} ú#覨r¬ñÀ. e?ùæš«·û@¶Y—ç Z°\’ñš¬oÏÍÝ®>íu¿«):PìÕo0ìzåØí[øýÊ ÀÓ€€6Ç¿”í!&#Ђ7Fâe¡Øîäc “ ·nãs rã›lpC]Ø3÷mŠO$ǃÊosg}`Óì õo vçÌÛWφRÚòÊÊ5|,)M“ý÷™Çôø†ÞcZß·Èÿ’AˆR4ÆýâV®VÖp9g.Û¬?QYú&‡6s`ëBÇý=  FÎ)íGˆ€íUPܨŠ&lƒkN,Xi/W=äú5ŠÞ5.LéRnØö¡4‰ØzV{éûàjШƻ ¿E¬/±¯ƒi´Dj”~Íý³nF3ø6hþ¨SNÕ…›¾À«9g¶úºëÂ}Ò_Ë4¥êâ<†mt’ÉÂ}¶l'ˆõH~xìtÓC¯x½ïÇÔLëkrÃgl¯¸AÏ|ÆÐåš¹,“ÓÖúü÷üy Zwü%Ä–4:¦Ú"eñËÅøà¯ï0û9ª™šÛ÷é8ü—¬ªt.$_!©f54_î€æ ±yTh¾*)Ì6þ[–'øñC?"†oÖešŠÅ7ìº_($†SNïË C¥{J‡0ÜL^Ä?Ì öî^ºu£Hx”é#íRöºßmm€ŸZu¼»qÁkð쳟 ¼ðùAâ5ÇY±lž±dûäçP;âgéÕØK•¾1}ÑR=¬˜Ù^ŽZ@ËÌ7-í³W㆗ •hº ‹-Ù¥yN æ«§°z&š}¢]˵kõ v½{P»Þ?¨]ß=¨]zP»žÔ®õƒÚ¿½am’k-ŠPkùŽíK©¿ ˜Õ¿:fí„Pø»Ïð°ºY1ßl½’´D«ªA+X`cJ:©?qe¸=ñø¨Ï~<Š+šn!åñ¬ß@«i,è›fð2É|馟Š×ë¦ èC§RÒ €§ÑŠÆx$õçИÏú´¶æk>lgA'ô*–`½{ð69w[Pž…^O§ÏÔ”ªa^óµYˆ%$Uº\Ï¿Yb5 ¨|èL`)¤òµJ’êS÷bjàFµ3lŽìËÞ#ûrèã¤Î7s&ýŒëÕ`ÃÖ|¸Y14·ê Á<ŸšIì–ó·x¿§ù‘' ²ƒf­—…Äxko¼mbÀŒCW»¡yûu‹{]ÙïP»¨„üÊFÿX¸+uÏ5‘wj!#E­£ž­DM“Rûrǵ¹ Q'à;ÚýÿäãÿPKÝ”f¡ÒB2PKŠä4I0((meta.xml OpenOffice.org/2.0$Linux OpenOffice.org_project/680m1$Build-89902006-06-27T12:48:522006-07-04T19:16:50it-IT18PT11H34M36SPKŠä4Thumbnails/thumbnail.png èõ‰PNG  IHDRq ;ƒZ ÞIDATxœí]Ùvë* m×ÊÿÿrîÍiÝbªak`°£ý’Ø!’ Îãù|~®Çj q”o€Râ PJ¼J‰7@)ñ(%Þ¥Äd|~~þz??gò¾œ_9¾¿:Ô^Sh;ÍÑ4í õíPåGû}ã“’R¥ª}—Sbß!ËS¯Ñ¶å-Un©c‘ËÂërJ,ü…¨ÄÖ,H4”¹áh4p¦¹çi‘%™-q[€¬%Ty»Vp4mÔúAÑr÷u)§Öº^.Nv¤ÌJ¯ÉßÖy´7)Bޱ´®¶¦d´•…«/ñµŽ§§ïGZo€Râ PJ¼'ïçµPz×Ao]®ž‡ŸµN¤¿áw&R<9Ùu=ü¬u"2S0<Y!ÍÙœfuH{¢åQúL4mÇ(pð‹\Å5ŒYµíË)zk§VšÅ#g®–#óã‡Ñ Ö†w…k&ÎJOí˜Û¬¹m™¶œª××i·k¤ÔWŽlå¼;X%¢é0naÖöÒ¨‡¤ßŸ£hW¡—![&”5ÞêLD7aµû?ä;%¼–Жà©Ïmxå@­Ž„–V‰‘MX‰ïJ‘dsÖìËœÅÃÒn#LàfuG¨JŒ˜.´®ä@¡|ßY¹ªgŽg߯°ù.ztbæ Î÷ÈåñÂÞiÔ+D ëdA½FÄãFú­ÝCg ÇX4LñN-OØ “Šô)ãØˆÖnÌŽ'ëÒ׫5-éŽM)h>¶plv‹)'*ê” Žw¿•c©cÓòÔxK¹Ø~`Qž–¶Zpü)‡IŠ‘6Z~ýýãûùŒ QIKd· ­OÖ‰×çù¼ UGãÑFfcÄ2Pa*5y8™ZرáÜg˓ϕ?™rÏì”Ê£ÖD GZXf™TŽÐ¦86á°à{zFWk;#DÒê¯væ ™ˆ,ò¯kwFÅ8ÙSòú¤œ ¹­´t0Úk΄RS_Z#@.ÔD{dò8PٴК¨:$F››Õæl5XïÔͬ4^ïá¯0ø= ˆÑz~p?„v#0Ï@‘é}½À¹Öª÷J7þ<}‚ÞåÏúÇЉ^2Õ>Ièos|%Ìž&8 ¨ÇIÞKž]žñVË“±“Âÿa†<ôy«ý‚p<ÛâÖ¹ þï“cÃ.ö`¢\KÑ!9ÚÂ_„ŠNªSŠÉÇ4s꩟eb£ñekm¬1îŒeÂlN9s‰Äm’éõìXeˆ¤û¸4#ÚoDFË.I Øœ¶OšŠ£f@5ÃO« Ù°ò¶.7ÓA)4é,ñhïy3B^Y¤à‘aLI€{øàqueqzPj¥33‹ïHû}"E{ðñ —±ïèá×{¢»#õ¸9A­`å ^E/lgN-<¯4[Fbº9ÕRuHŠîG^Í,z;¥îS@c-F¤êx•&Ú©‹«#ɲâ¡Ù±Ac½,G™½=M?§¾¾®þËÒn³›LžÕÚü»?NfÇf§Ø/Úf¿GÌ8Ú^æRq€=ž!¥Å¬ñ–TÇ’6ãÌ{TÎVFŠWFZO‡HJpøA)¤~ÄìfÉé•g%Ï[ü>±Cèð°µ®…>ºNDÖŸ«Å–쟛 °®uÑ-,´‰GvNv5Ä?7‰bÖÓì îèWQ…½QŽÍ pZ3f%—{lijöçâ4# ~ï`PÊ´öÃÍ)¥ÌB.R½ÓììLC967@)ñ(%Þ¥Äà”×bÅщaMÉÓ&×GmvÏ8÷'®ÅqYqž” ×Îçp§á¨-p#–•·ž ²´žqš×š¸¦çé{_ÜN@Î-ýÉØxÍ©täåßÒõ#âHPãÓߣf3E? Kß(e:cV´½rü*Ø¿J‰7@)ñp+‘‹'ûûRÜÙ×ó¬+Ç!j}óÆ~ÖØÕü‡_h Õ—¡)%.¦”R€ÖtRW‹© %§ûYå¢ÊÕ8é’²³ðÐfw_&Ýéâ#ýž”7{f‚%Û•kF¬¶—Š%\]þÊ;½J‰7@)ñ(%ÞC”¨mY½>µ8ë+þü“i$pn„}lhI”’±Üœf=4ïŒ?qâì'œÊÔÔ,³aùL,Ä‘¦Ä»…/„w1Zx#)9^Ð1䥵¥„¹˜'fÖ)|aØKk=¦U:`[à1üG¦¥„ñ€Þža9CáWð~ó0ÇÀãÕruJ¹>LýÍ~)i †86¥¬¹Øúí ®—e::™õ#|û#ŽÒáh‹ŒYéH‰9í¦Ñfl-ÚžBùjËI4­x@‹£Ñc[Yœ}ØW¢=.üÕ¿ÞËj¨09­£{ã?*­¡†¢Î°IEND®B`‚PK< h  PKŠä4 settings.xmlÍY]SâJ}¿¿ÂÊë-—Ù]¡„­¢¸€âÛ4$:™IÍL øë·'€å"ìr©º>d&ý•Ó§»'—?f=y!CÎJÖÙÛ:æq?dÓ’õЯŸ^X?Êÿ\òÉ$ô ès/‰€©S Jáy‚·3Y\,—¬D°"'2”EF"Eåy lu[ñãîb¦lqeFCöR²¥âb.—¦é—ôü ÓÜY¡PÈe««­g“pº«ªÅîª8çïŠô c2eŽmçs‹ßÖÉÒÈßBS^Åaå~ùr©`ñq*ˆtlN–—µi% U_CHߣfmºï÷{¸ß@ú<¶V+jãJÈ”U>³mç2÷YÈî‚›0Qf$C_›D;ß ùeß@8 6Û]ÈÿºŸð^ÀÓ.øˆ2¨„MA®)sN0«¬Dûéh°Šà©„÷áÒO#Ÿ†Ì‡øŸCµaÙ=˜b¾[Àþš¥R „¯UÖ`>àAn…žs‘ß_ê¶LÉ;{ÂbÊpLÁD¢d‚ ¤v&·»-Eœ‹ò/]áJñh£l{ïô{â<꣤u°\ `{¡uâ).6‹Ýר†ìO_xa[*O•[ryÃʼn¹my™ë›7`aÙ½-.$‚(,lÿ¥&¹¾ß!‚ô "¡OsÁщ²ƒ£º ë.¬óÏ.áý›ü»Di¢o¢: ú²DcpæmMì\bŸ¨MÄ¿„âÙžHœ2.  ©P 4L5˜Io°: Ì)UŤž¹zè…[>ÞZŠpcñ@êi¢˜âwJ27:$¡õ@%ël -˜’ÝM&˜È&‚•ù¡k`‡iŒ–WGp…´Š€ú óu-D·|%dDÌ­ÜŽ&g,eÀ^ÊM_ ÈV9VN ØŸ‰±ã\îOoþÍ·ŸGÃÙëøz÷k£·–ûÿý»?Ü?¼Åo#§.ÇÎŒÂͽÓzÛ¸uèº-—.är× zøõÊǽ¨v¯ëö¨çΪ¬2'ïöÓc£à9í`|]OÝ~n¥Õ¨€kƒÄǽdXH:ƒÊ«ÇºóÑÚÕ¨ýê]Sê½Ù(#‹!íô¯Ò–«Ñã-C™/£a|æwÕÊïô]Ùª¦i³æþ99>¿}yz¬Ø¤fÏÛnœzè $îû°þœ‡ʼ¸ê֯޶3¸=vƒê´T:.c\eíÁöªµ'»79ñ»@|Îè§4?êeÙôyÆU &2 u]Í0•¡MôÈH7äÆ1?H5¢ÈñÅ×ud’Ìzä‹#”;V¥\š(µZÉ5åcBkËÓÝv™(† ùŸ·+CÂ: óT’%‰ Ópʼ=Åã—áŸÔPË!0Z[šûõg'Âû”ò‹¹×Ò ¢ýy4ZHP4|¦¾Ò ÖÉl»’ Å+CD- ß±»ñ3FÚT• å†Z¨†l’1¼ƒßDÇ,¡ÎEBOýg嶺z ®ãíÝ¥b3>Õx›ã<‹Ý¹vÍUJHÔ‹SZyT‹¹Cpc;mJþ5Æ+=E•Ržf:pø«æ5Î{8ÍF„ù&ÙìhkOšÊüm"U8™ë´‘ÃP-ÂB+È‹É4E.ç¿*f€½¤z}î ß»èªKæPK. x§PKŠä4^Æ2 ''mimetypePKŠä4MConfigurations2/statusbar/PKŠä4'…Configurations2/accelerator/current.xmlPKŠä4ÜConfigurations2/floater/PKŠä4Configurations2/popupmenu/PKŠä4JConfigurations2/progressbar/PKŠä4„Configurations2/menubar/PKŠä4ºConfigurations2/toolbar/PKŠä4ðConfigurations2/images/Bitmaps/PKŠä4¡7DÁ'Å -content.xmlPKŠä4Ý”f¡ÒB2 fstyles.xmlPKŠä4I0((p&meta.xmlPKŠä4< h  ¾*Thumbnails/thumbnail.pngPKŠä4¯Ü¼F« 5settings.xmlPKŠä4. x§ :META-INF/manifest.xmlPKî[<dballe-7.7/doc/intro.tex0000644000175000017500000000427712652630043012170 00000000000000\section{What is \dballe{} } \dballe{} is a database for punctual meteorological data intended to complement the existing tools to manage grid-based data. These are the main characteristics of \dballe{}: \begin{itemize} \item it is temporary, to be used for a limited time and then be deleted. \item does not need backup, since it only contains replicated or derived data. \item write access is enabled for its users. \item it is fast for both read and for write access. \item it is based on physical principles, that is, the data it contains are defined in terms of omogeneous and consistent physical data. For example, it is impossible for two incompatible values to exist in the same point in space and time. \item it can manage fixed station and moving stations such as airplanes or ships. \item it can manage both observational and forecast data. \item it can manage data along all three dimensions in space, such as data from soundings and airplanes. \item it can work based on physical parameters or on report types. \end{itemize} \section{Intended usage of this guide} This guide is the reference for usage and maintenance of \dballe{}. It provides informations about installing a \dballe{} system and keeping it up to the changing requirements of the users. This guide is intended to be used by advanced users of \dballe{} that want to know more about the system and perform some troubleshooting, and to system administrators who need to install and maintain \dballe{} in their system. \section{What this guide is not} This guide does not intend to be a guide for the Fortran API: for that, the reader is referred to the document ``Quick guide of the Fortran API''\cite{FAPI}. This guide does not intend to be a guide for coding with \dballe{}. For that, the reader is referred to the document ``libdballe Documentation''\cite{LibDoc}. This guide does not intend to be the reference guide for the commandline tools that are part of \dballe{}. For that, the reader is referred to the manpages\cite{DbaTblMan}\cite{DbaMsgMan}\cite{DbaDbMan} of the tools. You can however find (see \ref{ch-tools}) an introduction to the commandline tools in this guide, as well as some usage examples. dballe-7.7/doc/add_templates_to_manpage0000755000175000017500000000151712652630043015233 00000000000000#!/usr/bin/env python import sys, re, subprocess SPLIT=re.compile(r"\s*,\s*") # Read the aliases templates = [] proc = subprocess.Popen(["./run-local", "dbamsg", "convert", "--template=list"], stdout=subprocess.PIPE) out, err = proc.communicate() for line in out.split("\n"): if not line: continue name, desc = line.split(" - ") templates.append(dict(name=name, desc=desc)) templates.sort(key=lambda x: x["name"]) for line in sys.stdin: if line.startswith(".SH AUTHOR"): print r""" .SH TEMPLATE NAMES This is a list of possible template names for the \fB\-\-template\fP switch: .P """ for a in templates: print ".TP" print r"\fB%s\fP" % a["name"] print ".br" print a["desc"] print r""" .P \-\-template=list will also print the list. """ print line, dballe-7.7/doc/install.tex0000644000175000017500000001674712652630043012510 00000000000000\section {Installing \dballe{} } \dballe{} should come prepackaged for your system on a {\tt RPM} or {\tt DEB} package. If that is the case, you can just install \dballe{} like any other software in your system. In case the packages are not good for you, or in case you are the one that needs to create the package, this section will show all the steps required for an installation of \dballe{} from scratch. % see procedure from script on spino Outline of the procedure: \begin{enumerate} \item Install the package dependencies \item Unpack the source \item Configure the source \item Compile the source \item Install the binaries \end{enumerate} Once installed, \dballe{} will provide a low-level C API, a high-level Fortran API and various commandline tools to import, export and manipulate meteorological messages. \subsection{Install the package dependencies} This table lists the dependencies needed to build \dballe{}: \begin{tabular}{|l|l|l|l|} \hline {\em Package} & {\em Type of dependency} & {\em Fedora package} & {\rm Debian package} \\ \hline unixodbc & Required & {\tt unixODBC-devel} & {\tt unixodbc-dev} \\ gperf & Required & {\tt gperf} & {\tt gperf} \\ popt & Required & {\tt } & {\tt libpopt-dev} \\ CNF & Only required for the Fortran API & {\tt starmet} & {\tt starmet} (unofficial, contact \dballe{} team) \\ g77 & Only required for unit tests & {\tt } & {\tt g77} \\ doxygen & Only required for documentation & {\tt doxygen} & {\tt doxygen} \\ tetex & Only required for documentation & {\tt tetex, tetex-latex} & {\tt tetex-bin} \\ latex2html & Only required for documentation & {\tt } & {\tt latex2html} \\ rst2html & Optionally required for pretty-printing of the README file & {\tt } & {\tt python-docutils} \\ \end{tabular} In order to run, \dballe{} requires an Unix GNU operating system with the following packages installed: \begin{tabular}{|l|l|l|l|} \hline {\em Package} & {\em Type of dependency} & {\em Fedora package} & {\rm Debian package} \\ \hline popt & Required & {\tt } & {\tt libpopt0} \\ CNF & Only required for the Fortran API & {\tt starmet} & {\tt starmet} (unofficial, contact \dballe{} team) \\ MyODBC & Required & {\tt MyODBC} & {\tt libmyodbc} \\ MySQL & Required if not accessed remotely & {\tt mysql >= 4.1.1 } & {\tt mysql-server-5.0} \\ \end{tabular} \subsection{Unpack the source} You should have receved the source tarball of \dballe{} in a file with a name like ``\tarball{}''. You can extract it with {\tt tar}: ``{\tt tar xf \tarball{}}'': this will create the directory ``\sourcedir{}'' with the extracted source. Enter the source directory to continue with configuring the source. \subsection{Configure the source} \dballe{} sources need to be configured before building, so that they can adapt to the host architecture and operating system. \dballe{} uses the standard GNU Autotools, which you may already be familiar with. Configuration is done using the {\tt ./configure} script: \begin{verbatim} ./configure \end{verbatim} \dballe{} allows some extra options to be passed to {\tt configure} to control the building process, for example to disable building the documentation or the unit test suite. These are the \dballe{}-specific parameters you can use to turn off compiling specific parts of the library: \begin{description} \item[\tt --disable-fortran] Disable generation of Fortran bindings. This allows the code to be compiled without having CNF installed, but the library will be impossible to use from Fortran. \item[\tt --disable-docs] Disable building of the documentation. This allows the code to be compiled without having {\tt doxygen}, {\tt tetex} and {\tt latex2html} installed, but there will be little or no documentation. \end{description} Other relevant {\tt configure} parameters are: \begin{description} \item[{\tt --prefix=dir}] Set the toplevel directory where \dballe{} will be install. By default this is {\tt /usr/local}. \item[{\tt --localstatedir=dir}] Set the toplevel directory where \dballe{} will store the indexes for fast-access to the table files. By default this is {\tt \$prefix/var}, and the table indexes are stored in {\tt \$localstatedir/cache/dballe}. \item[{\tt --sysconfdir=dir}] Set the toplevel directory where global configuration is kept. By default this is {\tt \$prefix/etc}, and the configuration is stored in {\tt \$sysconfdir/dballe}. \item[{\tt --disable-shared}] Disable building shared libraries. This is a 2x speedup in compilation time, and is very useful when debugging the library. \end{description} \subsection{Compile the source} Compiling the source is as you would expect: you just run ``{\tt make}'' and it does everything for you. You can run ``{\tt make check}'' after ``{\tt make}'' to run the library self-test; some tests may fail if a MySQL database named ``test'' is not accessible. \subsection{Install the binaries} Installing the binaries follows the usual procedure as well: just run ``{\tt make install}''. This will take care of installing all the built files in the right place. The installation of \dballe{} is now completed. Remember that \dballe{} applications need an ODBC DSN to connect to the database. The directory layout of \dballe{} after installation is described in \ref{install-dir-layout}. \subsection{Optional extra goodies} Besides what gets installed by {\tt make install}, there are a couple of extra things left in the source directory after compilation that may be useful: \begin{description} \item[{\tt README}] Contains informations about the current state of the development of \dballe{}. It is in reStructuredText format, and you can convert it into HTML using the tool {\tt rst2html} from {\tt python-docutils}. \item[{\tt doc/}] Contains the documentation built at build time, unless {\tt --disable-docs} was used when configuring the sources. You probably want to copy the relevant parts to a place where users can find it. \item[{\tt doc/fapi\_html}] Quick guide of the Fortran API, in HTML format. \item[{\tt doc/fapi.ps}] Quick guide of the Fortran API, in PostScript format. \item[{\tt doc/dox\_html}] libdballe documentation for the programmer, in HTML format. \item[{\tt doc/guide\_html}] DB-ALLe Manual for Advanced Users and Administrators, in HTML format. \item[{\tt doc/guide.ps}] DB-ALLe Manual for Advanced Users and Administrators, in PostScript format. \end{description} \section {\dballe{} directory layout} \label{install-dir-layout} These are the various files and directories installed by \dballe{} (assuming {\tt ./configure} was invoked with {\tt --prefix=/usr/local}, {\tt --localstatedir=/usr/local/var} and {\tt --sysconfdir=/usr/local/etc}): \begin{description} \item[{\tt /usr/local/bin}] \dballe{} tools: {\tt dbatbl}, {\tt dbamsg} and {\tt dbadb}. \item[{\tt /usr/local/share/man/man1}] Manpages for the \dballe{} tools. \item[{\tt /usr/local/include/dballe}] Include files for building applications that use \dballe{}. \item[{\tt /usr/local/lib}] Compiled libraries. \item[{\tt /usr/local/lib/pkgconfig}] pkg-config metadata about the library. \item[{\tt /usr/local/share/aclocal}] autoconf macro for using the library. \item[{\tt /usr/local/share/doc}] Documentation. \item[{\tt /usr/local/share/dballe}] Tables in text format. \item[{\tt /usr/local/etc/dballe}] Configuration files. \end{description} dballe-7.7/doc/guide.tex0000644000175000017500000000274412652630043012127 00000000000000%\documentclass[draft,a4paper]{book} %\documentclass[final,a4wide]{book} %\documentclass[final,12pt,a4paper,twoside]{book} \documentclass[final,12pt,a4paper,twoside]{book} %\usepackage[italian]{babel} \usepackage[ascii]{inputenc} \usepackage[T1]{fontenc} \usepackage{graphicx} \usepackage{epstopdf} \usepackage{moreverb} \usepackage{ifthen} % Include alcuni simboli non piú standard ma usati da gnuplot \usepackage{subfigure} \usepackage{epsfig} \title{DB-ALLe Manual for Advanced Users and Administrators} \author{Enrico Zini \hfil {\tt enrico@enricozini.com}} \newcommand{\dballe}{{\tt DB-ALLe}} \newcommand{\sourcedir}{{\tt dballe-0.4}} \newcommand{\tarball}{{\tt \sourcedir{}.tar.gz}} \newcommand{\srcinsert}[1]{% {\scriptsize \verbatimtabinput[4]{#1} }} %\newlength{\savedmarginparwidth} \newcommand{\figures}[2][!]{% \smallskip %\setlength{\savedmarginparwidth}{\marginparwidth} %\setlength{\marginparwidth}{0pt} \begin{minipage}[c]{\textwidth} \ifthenelse{\equal{#1}{!}}{}{#1:\\} #2 \end{minipage} \medskip %\setlength{\marginparwidth}{\savedmarginparwidth} } \makeindex \begin{document} \bibliographystyle{plain} \maketitle \tableofcontents %\listoffigures %\listoftables \chapter{Introduction} \label{ch-intro} \input{intro.tex} \chapter{Installation} \label{ch-install} \input{install.tex} \chapter{Maintainance} \label{ch-config} \input{maintainance.tex} \chapter{FAQ and Troubleshooting} \label{ch-trouble} \input{troubleshooting.tex} \appendix \bibliography{local} \end{document} dballe-7.7/doc/libdballe.dox.in0000644000175000017500000013400712652630043013341 00000000000000# Doxyfile 1.3.7 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libdballe # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 2 levels of 10 sub-directories under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, # Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en # (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, # Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = YES # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = YES # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../dballe # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = *.h *.c *.dox # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = test-utils-*.h # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. INPUT_FILTER = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = c_api # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = \ "F77_INTEGER_FUNCTION(a)=integer a" \ "F77_SUBROUTINE(a)=subroutine a" \ "LOGICAL(a)=logical a" \ "INTEGER(a)=integer a" \ "CHARACTER(a)=character a" \ "REAL(a)=real a" \ "DOUBLE(a)=double a" \ "TRAIL(a)=" # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = libwreport.doxytags = /usr/share/doc/libwreport-doc/apidocs/ # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = libdballe.doxytags # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO dballe-7.7/doc/local.bib0000644000175000017500000007264412652630043012066 00000000000000%%%==================================================================== %%% BibTeX-file{ %%% filename = "local.bib", %%% version = "2.01", %%% url = "http://localhost", %%% date = "1 Set 2005", %%% time = "11:33:02 CET", %%% author = "Enrico Zini", %%% address = "undisclosed", %%% telephone = "undisclosed", %%% FAX = "undisclosed", %%% checksum = "53966 3591 6748 66918", %%% email = "enrico at enricozini.com", %%% codetable = "ISO/ASCII", %%% keywords = "", %%% supported = "yes", %%% abstract = "", %%% docstring = "The checksum field above contains a CRC-16 %%% checksum as the first value, followed by the %%% equivalent of the standard UNIX wc (word %%% count) utility output of lines, words, and %%% characters. This is produced by Robert %%% Solovay's checksum utility.", %%% } %%% ==================================================================== @misc{FAPI, author={Enrico Zini}, title={Quick guide of the Fortran API} } @misc{LibDoc, author={Enrico Zini}, title={libdballe Documentation} } @misc{UserGuide, author={Enrico Zini}, title={DB-ALLe Manual for Advanced Users and Administrators} } @misc{DbaTblMan, author={Enrico Zini}, title={dbatbl Manpage} } @misc{DbaMsgMan, author={Enrico Zini}, title={dbamsg Manpage} } @misc{DbaDbMan, author={Enrico Zini}, title={dbadb Manpage} } % tse-published.ps % Presentazione di CTTE % Ottimo esempio di come sistemare la struttura dell'articolo @Article{Mori2002, author={Giulio Mori, Fabio Patern{\`o}, Carmen Santoro}, title={CTTE: Support for developing and analizing task models for interactive system design}, journal={IEEE Transactions on Software Engineering}, volume={28}, number={9}, year={2002}, month={September} } % http://giove.cnuce.cnr.it/concurtasktrees.html @misc{IntroCTT, author={Fabio Patern{\`o}}, title={ConcurTaskTrees Home Page}, url={http://giove.cnuce.cnr.it/concurtasktrees.html}, note={Available from http://giove.cnuce.cnr.it/concurtasktrees.html} } % deliverable mefisto @Misc{Mefisto, author={Fabio Patern{\`o} and Carmen Santoro}, title={Application of usability evaluation methods}, year={2000}, note={Project Mefisto, Deliverable 6, Part B: Notations and Related Tools Evaluation}, month={December} } % Observatii evaluare @misc{Observatii, author={Ana Maria Marhan}, title={CTTE 1.5.8b: usability evaluation}, year={2003}, month={Nov}, note={Documento interno al progetto} } % Tesi di Violante sui vari metodi di task analysis % thesis_violante_part1.pdf @PHDThesis{Violante, author={Francesco Fabio Domenico Violante}, title={OPTA: OPen Task Analysis}, school={Politecnico di Milano}, address={Milano, Italy}, } % Libro su CTT % book-task-paterno-1.pdf @Book{Paterno-ctt, author={Fabio Patern{\`o}}, title={ConcurTaskTrees: An Engineered Approach to Model-based Design of Interactive Systems} } % Semantica di CTT % last-del.zip @Misc{Semantica-ctt, author={Fabio Patern{\`o} and Carmen Santoro}, title={The ConcurTaskTrees Notation for Task Modelling}, year={2001}, month={May}, note={Guitare Project Document} } % Un qualche manuale di Gimp (usato per l'indagine cognitiva) @Book{Kylander:1999:GUM, author = "Olof Kylander and Karin Kylander", title = "The {GIMP} user's manual", publisher = "Coriolis Group Books", address = "Scottsdale, AZ, USA", pages = "xxiv + 895", year = "1999", ISBN = "1-57610-520-2", LCCN = "T385 .K866 1999", bibdate = "Mon Dec 06 16:18:41 1999", price = "US\$49.99, CAN\$73.99, UK\pounds 34.99", acknowledgement = ack-nhfb, } @Book{Bunks:2000:GG, author = "Carey Bunks", title = "Grokking the {GIMP}", publisher = "New Riders Publishing", address = "Carmel, IN, USA", pages = "342 (est.)", year = "2000", ISBN = "0-7357-0924-6", LCCN = "????", bibdate = "Fri Dec 15 06:47:10 2000", price = "US\$45.00", acknowledgement = ack-nhfb, } %% I vari task analysis % Introduzione di Paternò @Book{LibroPaterno, author={Fabio Patern{\`o}}, title={Model-based Design and Evaluation of Interactive Applications}, publisher={Springer Verlag}, year={1999}, month={Nov}, ISBN={1-85233-155-0} } % GOMS @Book{Card83, author = "Stuart K. Card and Thomas P. Moran and Allen Newell", title = "The Psychology of Human-Computer Interaction", pages = "469", publisher = "Lawrence Erlbaum Associates", address = "Hillsdale, NJ", year = "1983", keywords = "GENERAL DESIGN Psych EVALUATION Model Theory", MRnumber = "B.Card.83", ISBN = "0-89859243-7", URL = "http://www.erlbaum.com/149.htm", note = "(pbk) 0-89859859-1 (hdbk); OCLC 9042220", contents = "(not listed)", } %UAN @Article{Hartson92, author = "H. Rex Hartson and Philip D. Gray", title = "Temporal Aspects of Tasks in the User Action Notation", journal = "Human-Computer Interaction", series = "Articles", volume = "7", number = "1", pages = "1--45", year = "1992", copyright = "(c) Copyright 1992 Lawrence Erlbaum Associates", MRnumber = "J.HCI.7.1.1", abstract = "The need for communication among a multiplicity of cooperating roles in user interface development translates into the need for a common set of interface design representation techniques. The important difference between design of the interaction part of the interface and design of the interface software calls for representation techniques with a behavioral view -- a view that focuses on user interaction rather than on the software. The User Action Notation (UAN) is a user- and task-oriented notation that describes physical (and other) behavior of the user and interface as they perform a task together. The primary abstraction of the UAN is a user task. The work reported here addresses the need to identify temporal relationships within user task descriptions and to express explicitly and precisely how designers view temporal relationships among those tasks. Drawing on simple temporal concepts such as events in time and preceding and overlapping of time intervals, we identify basic temporal relationships among tasks; sequence, waiting, repeated disjunction, order independence, interruptibility, one-way interleavability, mutual interleavability, and concurrency. The UAN temporal relations, through the notion of modal logic, offer an explicit and precise representation of the specific kinds of temporal behavior that can occur in asynchronous user interaction without the need to detail all cases that might result.", contents = "(not listed)", } @Book{Hix93, author = "Deborah Hix and H. Rex Hartson", title = "Developing User Interfaces: Ensuring Usability Through Product and Process", pages = "381", publisher = "John Wiley \& Sons", address = "New York, New York", year = "1993", MRnumber = "B.Hix.93", ISBN = "0-471-57813-4", note = "OCLC QA 76.9 U83 H59", contents = "(not listed)", } % GTA @Article{Veer96, author="G. van der Veer and B. Lenting and B. Bergevoet", title="GTA: Groupware task analysis - modeling complexity", journal="Acta Psychologica", volume="91", pages={297--322}, year="1996", url="citeseer.nj.nec.com/vanderveer96gta.html" } % Intent @InProceedings{1998:icre:leveson, author = "N. G. Leveson", title = "Intent Specifications: An Approach to Building Human-Centered Specifications", booktitle = "Proceedings: 3rd International Conference on Requirements Engineering", publisher = "IEEE Computer Society Press", ISSN = "1097-0592", ISBN = "0-8186-8356-2", year = "1998", pages = "204--213", annote = "incomplete", } % Petshop @Article{Bastide99, author = "R. Bastide and P. Palanque", title = "A visual and formal glue between application and interaction.", journal = "Journal of Visual Languages and Computing", volume = "10", number = "5", pages = "481--507", year = "1999", keywords = "Petri nets, interactive software, software engineering, software interfaces, software specification;", abstract = "The construction of interactive software is known to be a difficult task. As far as the non-interactive part of the application is concerned, designers can find support in the field of software engineering, using object-oriented design methods for example. With regard to the user interface per se, a number of interactive tools (interface builders) are available, that allows creating interactively the look and feel of the interface. However, relating an object-oriented design with a proper user-interface design is still a matter of craft and experience, and few techniques permit the seamless integration of the two. The work presented here aims at bridging this gap. The paper proposes a visual language, based on Petri nets, for the design of the dialogue of interactive systems. This language allows specifying both activation and rendering on the one hand, and provides a seamless integration with an object-oriented design on the other.", } % Teallach @inproceedings{Teallach, author = "P. Barclay and T. Griffiths and J. McKirdy and N. W. Paton and R. Cooper and J. Kennedy", title = "The Teallach Tool: Using Models for Flexible User Interface Design", booktitle = "Computer-Aided Design of User Interfaces II (CADUI)", pages = "139-158", publisher = "Kluwer", month = jan, year = 1999, note = "ISBN 0792360788" } %% Metodi di indagine % Lo Sperandio @Book{Sperandio, author = "Jean-Claude Sperandio", title = "La psicologia in ergonomia", publisher = "Societ{\`a} Editrice Il Mulino", address = "Bologna", pages = "210", year = "1983", ISBN = "88-15-00165-4", } % L'Hackos-Redish @Book{Hackos98, author = "JoAnn T. Hackos and Janice C. Redish", title = "User and Task Analysis for Interface Design", pages = "488", publisher = "John Wiley \& Sons", year = "1998", MRnumber = "B.Hackos.98", ISBN = "0-471-17831-4", contents = "(not listed)", } % Zammuner @Book{Zammuner, author={V.L. Zammuner}, title={Tecniche dell'intervista e del questionario}, publisher="Societ{\`a} Editrice Il Mulino", address="Bologna", year={2000} } % Libro interview di Yuwei @Book{Brenner, author={M. Brenner and J. Brown and D. Canter}, title={The Research Interview: Uses and Approaches}, publisher={Academic Press}, year={1985}, ISBN={0-12-131580-0} } %% Information Visualization @Book{infovis, editor = "Stuart K. Card and Jock D. Mackinlay and Ben Shneiderman", title = "Readings in information visualization: Using vision to think", publisher = "Morgan Kaufmann Publishers", year = "1999", address = "San Francisco", } @TechReport{Furnas, author = "G. W. Furnas", title = "The {FISHEYE} View: {A} New Look at Structured Files", institution = "Bell Laboratories", address = "Murray Hill, New Jersey 07974, U.S.A.", type = "Technical Memorandum", number = "\#81-11221-9", month = "12~" # oct, year = "1981", postscript-url = "http://www.si.umich.edu/~furnas/POSTSCRIPTS/FisheyeOriginalTM.ps", postscript-doc = "00000657.ps", } @Article{Spence82, author = "Robert Spence and Mark Apperley", title = "Data Base Navigation: An Office Environment for the Professional", journal = "Behaviour and Information Technology", volume = "1", number = "1", pages = "43--54", year = "1982", copyright = "(c) Copyright 1982 Taylor \& Francis Ltd.", MRnumber = "J.BIT.1.1.43", abstract = "The potential of the computer to assist in the everyday information handling activities of professional people has received little attention. This paper proposes a number of novel facilities to produce, for his purpose, an office environment in which needed item of information can rapidly be sought and identified. It involves a new display technique which overcomes the classical {"}windowing{"} problem, and the use of natural dialogues utilizing simple actions such as pointing, gesturing, touching and spoken commands. The simple dialogue makes the scheme well suited to the professional person, who is most likely unwilling to learn complex command languages. Little disturbances to the appearance of the office need be involved.", } @InProceedings{Rao94a, author = "Ramana Rao and Stuart K. Card", booktitle = "Proceedings CHI 94", institution = "Xerox Palo Alto Research Center", pages = "318--322", publisher = "ACM", title = "{T}he {T}able {L}ens: {M}erging {G}raphical {R}epresentations in an {I}nteractive {F}ocus+{C}ontext {V}isualization for {T}abular {I}nformation", year = "1994", } @Article{Hyperbolic, author = "John Lamping and Ramana Rao", title = "The Hyperbolic Browser: {A} Focus + Context Technique for Visualizing Large Hierarchies", journal = "Journal of Visual Languages and Computing", year = "1996", volume = "7", number = "1", pages = "33--35", } @TechReport{Lifelines, year = "1995", title = "LifeLines: Visualizing personal histories", URL = "http://visinfo.zib.de/EVlib/Show?EVL-1995-153", author = "Catherine Plaisant and Brett Milash and Anne Rose and Seth Widoff and Ben Shneiderman", abstract = "LifeLines provide a general visualization environment for personal histories that can be applied to medical and court records, professional histories and other types of biographical data. A one screen overview shows multiple facets of the records. Aspects, for example medical conditions or legal cases, are displayed as individual time lines, while icons indicate discrete events, such as physician consultations or legal reviews. Line color and thickness illustrate relationships or significance, scaling tools and filters allow users to focus on part of the information. LifeLines reduce the chances of missing information, facilitate spotting anomalies and trends, streamline access to details, while remaining tailorable and easily sharable between applications. The paper describes the use of LifeLines for youth records of the Maryland Department of Juvenile Justice and also for medical records. User's feedback was collected using a Visual Basic prototype for the youth record. Techniques to deal with complex records are reviewed and issues of a standard personal record format are discussed.", language = "en", month = sep, keywords = "Visualization, history, timeline, personal record, justice, medical record screen design, overview, screen management", number = "CS-TR-3523", institution = "HCIL Dept. of Computer Science, University of Maryland", } @TechReport{EVL-1995-154, year = "1995", title = "Browsing Hierarchical Data with Multi-Level Dynamic Queries and Pruning", URL = "http://visinfo.zib.de/EVlib/Show?EVL-1995-154", author = "Harsha Kumar and Catherine Plaisant and Ben Shneiderman.", language = "en", month = mar, keywords = "Browsing, Hierarchical, Dynamic Queries, Pruning, Tree-browser, visualization tool,filtering", number = "CS-TR-3474", institution = "HCIL Dept. of Computer Science, University of Maryland", } @InProceedings{Bederson94, author = "Benjamin B. Bederson and James D. Hollan", title = "Pad++: {A} Zooming Graphical Interface for Exploring Alternate Interface Physics", booktitle = "Proceedings of the ACM Symposium on User Interface Software and Technology", series = "Visualization I", pages = "17--26", year = "1994", copyright = "(c) Copyright 1994 Association for Computing Machinery", keywords = "Interactive user interfaces, Multiscale interfaces, Zooming interfaces, Authoring, Information navigation, Hypertext, Information visualization, Information physics", MRnumber = "C.UIST.94.17", URL = "http://www.acm.org/pubs/articles/proceedings/uist/192426/p17-bederson/p17-bederson.pdf", abstract = "We describe the current status of Pad++, a zooming graphical interface that we are exploring as an alternative to traditional window and icon-based approaches to interface design. We discuss the motivation for Pad++, describe the implementation, and present prototype applications. In addition, we introduce an informational physics strategy for interface design and briefly compare it with metaphor-based design strategies.", } @Article{JGraph, author = "Jay Bagga and Adrian Heinz", title = "{JGraph} --- {A} {Java} Based System for Drawing Graphs and Running Graph Algorithms", journal = "Lecture Notes in Computer Science", volume = "2265", pages = "459--??", year = "2002", CODEN = "LNCSD9", ISSN = "0302-9743", bibdate = "Tue Sep 10 19:09:04 MDT 2002", URL = "http://link.springer-ny.com/link/service/series/0558/bibs/2265/22650459.htm; http://link.springer-ny.com/link/service/series/0558/papers/2265/22650459.pdf", acknowledgement = ack-nhfb, } @misc{ArgoUML, title={ArgoUML Website}, author={Marko Boger and Jason Robbins and Linus Tolke and Markus Klink}, url={http://argouml.tigris.org/}, note={http://argouml.tigris.org/} } @PhdThesis{ArgoUMLErgonomia, title = "Cognitive support features for software development tools", author = "Jason Elliot Robbins", year = "1999", description = "Thesis (Ph. D., Information and Computer Science)--University of California, Irvine, 1999.; Includes bibliographical references (leaves 222-231).", oai = "oai:xtcat.oclc.org:OCLCNo/ocm43696229", school = "University of California, Irvine", subject = "Computer software--Development--Psychological aspects.; Computer-aided software engineering--Psychological aspects.; Object-oriented methods (Computer science); Problem solving.; Cognition.", } %% Processo @misc{yuwei, author={Yuwei Lin}, title={Culture, Creativity, and Innovation: practices of locally-crafted software}, institution={Science and Technology Studies Unit, Department of Sociology, University of York}, note={This paper is a work-in-progress under development for a presentation at a joint seminar of SATSU (Science and Technology Studies Unit) and HCI group at Computer Science and Psychology Departments at University of York, UK}, year={2003}, month={May} } @Misc{AgileManifesto, key = "AgileManifesto", author ={Kent Beck and Mike Beedle and Arie van Bennekum and Alistair Cockburn and Ward Cunningham and Martin Fowler and James Grenning and Jim Highsmith and Andrew Hunt and Ron Jeffries and Jon Kern and Brian Marick and Robert C. Martin and Steve Mellor and Ken Schwaber and Jeff Sutherland and Dave Thomas}, title = "Manifesto for Agile Software Development", url = "http://agilemanifesto.org", note = "Available from: http://agilemanifesto.org", } @misc{Cockburn1, author={Alistair Cockburn}, title={A methodology per project}, url={http://alistair.cockburn.us/crystal/articles/mpp/methodologyperproject.html}, note={Available from: http://alistair.cockburn.us/crystal/articles/ (cont.) /mpp/methodologyperproject.html} } @misc{Cockburn2, author={Alistair Cockburn}, title={Just-In-Time Methodology Construction}, url={http://alistair.cockburn.us/crystal/articles/jmc/justintimemethodologyconstruction.html}, note={Available from: http://alistair.cockburn.us/crystal/articles/ (cont.) /jmc/justintimemethodologyconstruction.html} } @inproceedings{Wood1, author = {William A. Wood and William L. Kleb}, title = {Extreme Programming in a Research Environment}, booktitle = {Proceedings of the Second XP Universe and First Agile Universe Conference on Extreme Programming and Agile Methods - XP/Agile Universe 2002}, year = {2002}, isbn = {3-540-44024-0}, pages = {89--99}, publisher = {Springer-Verlag}, } @Article{Wood2, author = "William A. Wood and William L. Kleb", title = "Exploring {XP} for Scientific Research", journal = "IEEE Software", volume = "20", number = "3", pages = "30--36", month = may # "\slash " # jun, year = "2003", CODEN = "IESOEG", ISSN = "0740-7459", bibdate = "Fri Oct 24 16:32:01 MDT 2003", URL = "http://www.computer.org/software/so2003/s3030abs.htm; http://dlib.computer.org/so/books/so2003/pdf/s3030.pdf", acknowledgement = ack-nhfb, } @Book{DesignPatterns, author = "Gamma and Helm and Johnson and Vlissides", title = "Design Patterns Elements of Reusable Object-Oriented Software", publisher = "Addison-Wesley", address = "Massachusetts", year = "1995", ISBN = "0-201-63361-2", descriptor = "Design, Objektorientierung", annote = "Objektorientierte Software Loesungen fuer haufig auftretende Design-Probleme werden in katalogisierter Form mit Anwendungsbeispielen und Implementierungsbeispielen in C++ oder Smalltalk dargestellt.", } %% Ergonomia @Book{Norman, author={Donald A. Norman}, title={La caffettiera del masochista - Psicopatologia degli oggetti quotidiani}, publisher={Giunti}, address={Firenze}, year={1997}, ISBN={88-09-21027-1} } @Book{Mantovani, author={Giuseppe Mantovani}, title={Comunicazione e identit{\`a} - Dalle situazioni quotidiane agli ambienti virtuali}, publisher="Societ{\`a} Editrice Il Mulino", address="Bologna", year={1995}, ISBN={88-15-04772-7} } @Book{Cooper99, author = "Alan Cooper", title = "The Inmates Are Running the Asylum: Why High Tech Products Drive Us Crazy and How to Restore the Sanity", pages = "300", publisher = "Sams", year = "1999", MRnumber = "B.Cooper.99", ISBN = "0-67231649-8", contents = "(not listed)", } @misc{Affordance, author={Donald A. Norman}, title={Affordances and Design}, url={http://www.jnd.org/dn.mss/affordances-and-design.html}, note={Available from: http://www.jnd.org/dn.mss/affordances-and-design.html} } @misc{Creativita, author={Maurizio Boscarol}, title={Usabilit{\`a} e creativit{\`a}}, url={http://www.usabile.it/172002.htm}, note={Available from: http://www.usabile.it/172002.htm}, year={2002}, month={Sep} } @misc{Euristiche, author={Jakob Nielsen}, title={Ten Usability Heuristics}, url={http://www.useit.com/papers/heuristic/heuristic_list.html}, note={Available from: http://www.useit.com/papers/heuristic/heuristic{\_}list.html}, } @misc{ValutazioneEuristica, author={Jakob Nielsen}, title={How to Conduct a Heuristic Evaluation}, url={http://www.useit.com/papers/heuristic/heuristic_evaluation.html}, note="Available from: http://www.useit.com/papers/heuristic/heuristic{\_}evaluation.html", } @incollection{Stress, author={Bangara S. and Rizzo A. and Vian M.}, title={Organizzazione del lavoro, decisione, fatica mentale e stress}, pages={21--49}, booktitle={Stress e lavoro - Temi, problemi, il contributo della sociologia ed i rapporti interdisciplinari}, publisher={Franco Angeli}, address={Milano}, year={1991}, note={Raccolta curata da Michele La Rosa} } @incollection{Errori, author={Bagnara S.}, title={Tecnologie dell'informazione e prospettive di ergonomia cognitiva}, booktitle={Interazione col computer e processi formativi: ipotesi di lavoro}, note={A cura di D. Gilli e A. Grimaldi}, publisher={FrancoAngeli}, address={Milano}, year={1990} } @InProceedings{Green89, author = "T. R. G. Green", title = "Cognitive Dimensions of Notations", booktitle = "Proceedings of the HCI'89 Conference on People and Computers V", series = "Cognitive Ergonomics", pages = "443--460", year = "1989", copyright = "(c) Copyright 1989 British Informatics Society Ltd.", keywords = "Computer languages, Opportunistic planning, Cognitive dimensions", MRnumber = "C.BCSHCI.89.443", abstract = "'Cognitive dimensions' are features of computer languages considered purely as information structures or notations. They therefore apply to many types of language -- interactive or programming, high or low level, procedural or declarative, special purpose or general purpose. They are 'cognitive' dimensions because they control how (or whether) the preferred cognitive strategy for design-like tasks can be adopted; it has repeatedly been shown that users prefer opportunistic planning rather than any fixed strategy such as top-down development. The dimension analysis makes it easier to compare dissimilar interfaces or languages, and also helps to identify the relationship between support tools and programming languages: the support tools make it possible to use opportunistic planning with notations that would otherwise inhibit it.", } @Article{Blackwell:2001:CDN, author = "A. F. Blackwell and C. Britton and A. Cox and T. R. G. Green and C. Gurr and G. Kadoda and M. S. Kutar and M. Loomes and C. L. Nehaniv and M. Petre and C. Roast and C. Roe and A. Wong and R. M. Young", title = "Cognitive Dimensions of Notations: Design Tools for Cognitive Technology", journal = "Lecture Notes in Computer Science", volume = "2117", pages = "325--??", year = "2001", CODEN = "LNCSD9", ISSN = "0302-9743", bibdate = "Sat Feb 2 13:05:19 MST 2002", URL = "http://link.springer.de/link/service/series/0558/bibs/2117/21170325.htm; http://link.springer.de/link/service/series/0558/papers/2117/21170325.pdf", acknowledgement = ack-nhfb, } @TechReport{CDtutorial, author = "T. Green and A. Blackwell", title = "Cognitive dimensions of information artefacts: a tutorial", institution = "BCS HCI Conference", version = "1.2", type = "Tutorial", month = "Oct", year = "1998", pdf-url = "http://www.cl.cam.ac.uk/users/afb21/CognitiveDimensions/CDtutorial.pdf", } @misc{blackwell00cognitive, author = "A. Blackwell and T. Green", title = "A Cognitive Dimensions questionnaire optimised for users", text = "Blackwell, A.F. & Green, T.R.G. (2000). A Cognitive Dimensions questionnaire optimised for users. In A.F.", year = "2000", url = "citeseer.nj.nec.com/blackwell00cognitive.html" } @InProceedings{CD-UML, author = "Kutar, M., Britton, C. and Barker, T.", title = "A Comparison of Empirical Study and Cognitive Dimensions Analysis in the Evaluation of UML Diagrams", booktitle = "Proceedings of the Fourteenth Annual Meeting of the Psychology of Programming Interest Group", publisher = "J. Kuljis, L. Baldwin and R. Scoble", year = "2002", pages = "1--14", } @article{Miller, author = {Miller,GA}, year = {1956}, title = {The magical number seven, plus or minus two: Some limtis on our capacity for processing information}, journal = {Psycological Review}, volume = {63}, pages = {81-97} } % - Qualche libro su Java e le librerie usate, comprese le API specification % - Design Patterns % - Qualche libro su LaTeX % - Il libro di task analysis di Paternò dballe-7.7/doc/troubleshooting.tex0000644000175000017500000000011212652630043014244 00000000000000\section{General} \section{Installation} \section{Fortran programming} dballe-7.7/doc/libdballef.dox.in0000644000175000017500000013375612652630043013521 00000000000000# Doxyfile 1.3.7 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libdballe Fortran bindings # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 2 levels of 10 sub-directories under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, # Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en # (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, # Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = YES # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = YES # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../fortran # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = error.cc binding.cc *.dox # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = test-utils-*.h # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. INPUT_FILTER = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = fortran_api # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = \ "F77_INTEGER_FUNCTION(a)=integer a" \ "F77_SUBROUTINE(a)=subroutine a" \ "LOGICAL(a)=logical a" \ "INTEGER(a)=integer a" \ "CHARACTER(a)=character a" \ "REAL(a)=real a" \ "DOUBLE(a)=double a" \ "TRAIL(a)=" # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = libdballef.doxytags # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO dballe-7.7/autogen.sh0000755000175000017500000000006512652630043011536 00000000000000#!/bin/sh # Rebuild the build system autoreconf -i dballe-7.7/depcomp0000755000175000017500000005601612652630066011126 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: dballe-7.7/install-sh0000755000175000017500000003546312652630066011560 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2014-09-12.12; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) # $RANDOM is not portable (e.g. dash); use it when possible 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. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: dballe-7.7/dballe/0000755000175000017500000000000012653425050011040 500000000000000dballe-7.7/dballe/types.h0000644000175000017500000004170512652630043012303 00000000000000#ifndef DBALLE_TYPES_H #define DBALLE_TYPES_H /** @file * Common base types used by most of DB-All.e code. */ #include #include namespace dballe { /** * Value to use for missing parts of level and time range values */ static constexpr int MISSING_INT = INT_MAX; /** * Calendar date. * * If year is 0xffff, then all the date is considered missing. Else, all fields * must be set. */ struct Date { unsigned short year; unsigned char month; unsigned char day; /// Construct a missing date Date(); /** * Construct from broken down values. * * A year of MISSING_INT constructs a missing Date. In any other case, * arguments are validated with Date::validate(). */ Date(int ye, int mo=1, int da=1); /// Copy constructor Date(const Date& d) = default; /// Create a date from a Julian day static Date from_julian(int jday); /// Check if this date is the missing value bool is_missing() const; /// Convert the date to Julian day int to_julian() const; /** * Write the date to an output stream in ISO8601 date format. */ void to_stream_iso8601(std::ostream& out) const; /** * Generic comparison * * Returns a negative number if *this < other * Returns zero if *this == other * Returns a positive number if *this > other */ int compare(const Date& other) const; bool operator<(const Date& dt) const; bool operator>(const Date& dt) const; bool operator==(const Date& dt) const; bool operator!=(const Date& dt) const; /// Raise an exception if the three values do not represent a valid date static void validate(int ye, int mo, int da); /// Return the number of days in the given month static int days_in_month(int year, int month); /// Convert a calendar date into a Julian day static int calendar_to_julian(int year, int month, int day); /// Convert a Julian day into a calendar date static void julian_to_calendar(int jday, unsigned short& year, unsigned char& month, unsigned char& day); }; /** * Time of the day. * * If hour is 0xff, then all the time is considered missing. Else, all fields * must be set. */ struct Time { unsigned char hour; unsigned char minute; unsigned char second; /// Construct a missing time Time(); /** * Construct from broken down values. * * A hour of MISSING_INT constructs a missing Time. In any other case, * arguments are validated with Time::validate(). */ Time(int ho, int mi=0, int se=0); Time(const Time& t) = default; /// Check if this time is the missing value bool is_missing() const; /** * Write the time to an output stream in ISO8601 extended format * (hh:mm:ss). */ void to_stream_iso8601(std::ostream& out) const; /** * Generic comparison * * Returns a negative number if *this < other * Returns zero if *this == other * Returns a positive number if *this > other */ int compare(const Time& other) const; bool operator<(const Time& dt) const; bool operator>(const Time& dt) const; bool operator==(const Time& dt) const; bool operator!=(const Time& dt) const; /** * Raise an exception if the three values do not represent a valid time. * * A value of 23:59:60 is allowed to accomodate for times during leap * seconds. */ static void validate(int ho, int mi, int se); }; /** * Date and time * * If year is 0xffff, then all the datetime is considered missing. Else, all * fields must be set. */ struct Datetime { unsigned short year; unsigned char month; unsigned char day; unsigned char hour; unsigned char minute; unsigned char second; /// Construct a missing datetime Datetime(); Datetime(const Date& date, const Time& time); /** * Construct from broken down values. * * A year of MISSING_INT constructs a missing Datetime. In any other case, * arguments are validated with Datetime::validate(). */ Datetime(int ye, int mo=1, int da=1, int ho=0, int mi=0, int se=0); /// Set the date from a Julian day static Datetime from_julian(int jday, int ho=0, int mi=0, int se=0); /** * Return a Datetime filling the parts set to MISSING_INT with their lowest * possible values */ static Datetime lower_bound(int ye, int mo, int da, int ho, int mi, int se); /** * Return a Datetime filling the parts set to MISSING_INT with their * highest possible values */ static Datetime upper_bound(int ye, int mo, int da, int ho, int mi, int se); /// Return a Date with this date Date date() const; /// Return a Time with this time Time time() const; /// Check if this datetime is the missing value bool is_missing() const; /// Convert the date to Julian day int to_julian() const; /** * Generic comparison * * Returns a negative number if *this < other * Returns zero if *this == other * Returns a positive number if *this > other */ int compare(const Datetime& other) const; bool operator==(const Datetime& dt) const; bool operator!=(const Datetime& dt) const; bool operator<(const Datetime& dt) const; bool operator>(const Datetime& dt) const; bool operator<=(const Datetime& dt) const; bool operator>=(const Datetime& dt) const; /** * Print to an output stream in ISO8601 combined format. */ void print_iso8601(FILE* out, char sep='T', const char* end="\n") const; /** * Write the datetime to an output stream in ISO8601 combined format. * * @param sep the separator character between date and time * @param tz the timezone string to use at the end of the datetime */ void to_stream_iso8601(std::ostream& out, char sep='T', const char* tz="") const; /** * Parse an ISO8601 datetime string. * * Both 'T' and ' ' are allowed as separators. */ static Datetime from_iso8601(const char* str); /** * Raise an exception if the three values do not represent a valid * date/time. * * A value of 23:59:60 is allowed to accomodate for times during leap * seconds, but no effort is made to check if there has been a leap second * on the given date. */ static void validate(int ye, int mo, int da, int ho, int mi, int se); /** * Convert a datetime with an hour of 24:00:00 to hour 00:00:00 of the * following day. */ static void normalise_h24(int& ye, int& mo, int& da, int& ho, int& mi, int& se); }; /** * Range of datetimes. * * The range includes the extremes. A missing extreme in the range means an * open ended range. */ struct DatetimeRange { /// Lower bound of the range Datetime min; /// Upper bound of the range Datetime max; DatetimeRange() = default; DatetimeRange(const Datetime& min, const Datetime& max) : min(min), max(max) {} DatetimeRange( int yemin, int momin, int damin, int homin, int mimin, int semin, int yemax, int momax, int damax, int homax, int mimax, int semax); /// Check if this range is open on both sides bool is_missing() const; bool operator==(const DatetimeRange& dtr) const; bool operator!=(const DatetimeRange& dtr) const; /// Set the extremes void set(const Datetime& min, const Datetime& max); /** * Set the extremes from broken down components. * * If yemin or yemax are MISSING_INT, they are taken as an open ended range * boundary. * * If any other *min values are MISSING_INT, they are filled with the * lowest possible valid value they can have. * * If any other *max values are MISSING_INT, they are filled with the * highest possible valid value they can have. */ void set(int yemin, int momin, int damin, int homin, int mimin, int semin, int yemax, int momax, int damax, int homax, int mimax, int semax); /** * Merge \a range into this one, resulting in the smallest range that * contains both. */ void merge(const DatetimeRange& range); /// Check if a Datetime is inside this range bool contains(const Datetime& dt) const; /// Check if a range is inside this range (extremes included) bool contains(const DatetimeRange& dtr) const; /// Check if the two ranges are completely disjoint bool is_disjoint(const DatetimeRange& dtr) const; }; /** * Coordinates * * When given as an integer, a latitude/longitude value is intended in 1/100000 * of a degree, which is the maximum resolution supported by DB-All.e. * * When given as a double a latitude/longitude value is intended to be in * degrees. * * Longitude values are normalized between -180.0 and 180.0. */ struct Coords { /// Latitude in 1/100000 of a degree (5 significant digits preserved) int lat; /** * Longitude in 1/100000 of a degree (5 significant digits preserved) and * normalised between -180.0 and 180.0. */ int lon; /// Construct a missing Coords Coords(); /// Construct a coords from integers in 1/100000 of a degree Coords(int lat, int lon); /// Construct a coords from values in degrees Coords(double lat, double lon); /// Check if these coordinates are undefined bool is_missing() const; /// Set from integers in 1/100000 of a degree void set(int lat, int lon); /// Set from values in degrees void set(double lat, double lon); /// Get the latitude in degrees double dlat() const; /// Get the longitude in degrees double dlon() const; /** * Compare two Coords strutures, for use in sorting. * * Sorting happens by latitude first, then by longitude. It is implemented * mainly for the purpose of being able to use Coords as a key in a sorted * container. * * @return * -1 if *this < o, 0 if *this == o, 1 if *this > o */ int compare(const Coords& o) const; bool operator==(const Coords& dt) const; bool operator!=(const Coords& dt) const; bool operator<(const Coords& dt) const; bool operator>(const Coords& dt) const; bool operator<=(const Coords& dt) const; bool operator>=(const Coords& dt) const; /// Print to an output stream void print(FILE* out, const char* end="\n") const; }; /** * Range of latitudes. * * When given as an integer, a latitude value is intended in 1/100000 of a * degree, which is the maximum resolution supported by DB-All.e. * * When given as a double a latitude value is intended to be in degrees. * * Values are matched between imin and imax, both extremes are considered part * of the range. * * Invariant: imin <= imax. */ struct LatRange { /// Minimum possible integer value static constexpr int IMIN = -9000000; /// Maximum possible integer value static constexpr int IMAX = 9000000; /// Minimum possible double value static constexpr double DMIN = -90.0; /// Maximum possible double value static constexpr double DMAX = 90.0; /// Minimum latitude int imin = IMIN; /// Maximum latitude int imax = IMAX; /// Construct a LatRange matching any latitude LatRange() = default; /// Construct a LatRange given integer extremes LatRange(int min, int max); /// Construct a LatRange given extremes in degrees LatRange(double min, double max); bool operator==(const LatRange& lr) const; bool operator!=(const LatRange& lr) const; /// Return true if the LatRange matches any latitude bool is_missing() const; /// Get the lower extreme as double double dmin() const; /// Get the upper extreme as double double dmax() const; /// Get the extremes as double void get(double& min, double& max) const; /// Set the extremes as integers void set(int min, int max); /// Set the extremes in degrees void set(double min, double max); /// Check if a point is inside this range (extremes included) bool contains(int lat) const; /// Check if a point is inside this range (extremes included) bool contains(double lat) const; /// Check if a range is inside this range (extremes included) bool contains(const LatRange& lr) const; }; /** * Range of longitudes. * * When given as an integer, a longitude value is intended in 1/100000 of a * degree, which is the maximum resolution supported by DB-All.e. * * When given as a double a longitude value is intended to be in degrees. * * Longitude values are normalized between -180.0 and 180.0. The range is the * angle that goes from imin to imax. Both extremes are considered part of the * range. * * A range that matches any longitude has both imin and imax set to * MISSING_INT. * * Invariant: if imin == MISSING_INT, then imax == MISSING_INT. An open-ended * longitude range makes no sense, since longitudes move alongide a closed * circle. */ struct LonRange { /// Initial point of the longitude range int imin = MISSING_INT; /// Final point of the longitude range int imax = MISSING_INT; /// Construct a range that matches any longitude LonRange() = default; /// Construct a range given integer extremes LonRange(int min, int max); /// Construct a range given extremes in degrees LonRange(double min, double max); bool operator==(const LonRange& lr) const; bool operator!=(const LonRange& lr) const; /// Return true if the LonRange matches any longitude bool is_missing() const; /// Get the lower extreme as double, or -180.0 if missing double dmin() const; /// Get the upper extreme as double, or 180.0 if missing double dmax() const; /** * Get the extremes in degrees. * * If is_missing() == true, it returns the values -180.0 and 180.0 */ void get(double& min, double& max) const; /// Set the extremes as integers void set(int min, int max); /// Set the extremes in degrees void set(double min, double max); /// Check if a point is inside this range (extremes included) bool contains(int lon) const; /// Check if a point is inside this range (extremes included) bool contains(double lon) const; /// Check if a range is inside this range (extremes included) bool contains(const LonRange& lr) const; }; /// Vertical level or layer struct Level { /// Type of the level or the first layer. See @ref level_table. int ltype1; /// L1 value of the level or the first layer. See @ref level_table. int l1; /// Type of the the second layer. See @ref level_table. int ltype2; /// L2 value of the second layer. See @ref level_table. int l2; Level(int ltype1=MISSING_INT, int l1=MISSING_INT, int ltype2=MISSING_INT, int l2=MISSING_INT) : ltype1(ltype1), l1(l1), ltype2(ltype2), l2(l2) {} /// Check if this level is fully set to the missing value bool is_missing() const; bool operator==(const Level& l) const; bool operator!=(const Level& l) const; bool operator<(const Level& l) const; bool operator>(const Level& l) const; /** * Generic comparison * * Returns a negative number if *this < other * Returns zero if *this == other * Returns a positive number if *this > other */ int compare(const Level& l) const; /** * Return a string description of this level */ std::string describe() const; /// Format to an output stream void to_stream(std::ostream& out, const char* undef="-") const; /// Create a cloud special level. See @ref level_table. static Level cloud(int ltype2=MISSING_INT, int l2=MISSING_INT); /// Print to an output stream void print(FILE* out, const char* undef="-", const char* end="\n") const; }; /** * Information on how a value has been sampled or computed with regards to time. */ struct Trange { /// Time range type indicator. See @ref trange_table. int pind; /// Time range P1 indicator. See @ref trange_table. int p1; /// Time range P2 indicator. See @ref trange_table. int p2; Trange(int pind=MISSING_INT, int p1=MISSING_INT, int p2=MISSING_INT) : pind(pind), p1(p1), p2(p2) {} /// Check if this level is fully set to the missing value bool is_missing() const; /** * Generic comparison * * Returns a negative number if *this < other * Returns zero if *this == other * Returns a positive number if *this > other */ int compare(const Trange& t) const; bool operator==(const Trange& tr) const; bool operator!=(const Trange& tr) const; bool operator<(const Trange& t) const; bool operator>(const Trange& t) const; /** * Return a string description of this time range */ std::string describe() const; /// Format to an output stream void to_stream(std::ostream& out, const char* undef="-") const; /// Time range for instant values static Trange instant(); /// Print to an output stream void print(FILE* out, const char* undef="-", const char* end="\n") const; }; } #endif dballe-7.7/dballe/main-msg.dox0000644000175000017500000000251312652630043013204 00000000000000/** @mainpage The DB-All.e msg library \section msg The Db-All.e msg library This library provides and encoding-independent message abstraction (see @ref msg.h and @ref msgs.h), and functions to intepret AOF, BUFR and CREX messages as physical information (see @ref bufrex_codec.h and @ref aof_codec.h). from the DB-All.e bufrex module, one main header file, @ref msg.h, which provides a container for parsed BUFR and CREX data and the BUFR and CREX encoding and decoding functions. The library also provides import/export functions from bufr, crex and aof, and to bufr and crex formats: see @ref bufrex_codec.h and @ref aof_codec.h \section bufrex The DB-All.e BUFR and CREX library This library provides BUFR and CREX encoding and decoding functions. There is only one main header file, @ref bufrex/msg.h, which provides a container for parsed BUFR and CREX data and the BUFR and CREX encoding and decoding functions. \section core The DB-All.e core library This library provides various core functionality for weather applications. You can use it for: \li The infrastructure for error handling (see @ref error.h) \li The infrastructure for working with physical quantities (see @ref var.h, @ref vartable.h, @ref conv.h, @ref record.h) \li The infrastructure for reading and writing meteorological data (see @ref file.h, @ref rawmsg.h) */ dballe-7.7/dballe/query.h0000644000175000017500000000446212652630043012303 00000000000000#ifndef DBALLE_QUERY_H #define DBALLE_QUERY_H #include #include #include #include #include namespace dballe { struct Record; /// Query used to filter DB-All.e data struct Query { virtual ~Query() {} /// Set the query values from the contents of a Record virtual void set_from_record(const dballe::Record& rec) = 0; /// Get the Datetime bounds set in this query virtual DatetimeRange get_datetimerange() const = 0; /// Set the Datetime range for this query virtual void set_datetimerange(const DatetimeRange& dt) = 0; /// Get the range of latitudes to be matched virtual LatRange get_latrange() const = 0; /// Set the range of latitudes to be matched virtual void set_latrange(const LatRange& latrange) = 0; /// Get the range of longitudes to be matched virtual LonRange get_lonrange() const = 0; /// Set the range of longitudes to be matched virtual void set_lonrange(const LonRange& lonrange) = 0; /// Get the level to be matched virtual Level get_level() const = 0; /// Set the level to be matched virtual void set_level(const Level& level) = 0; /// Get the time range to be matched virtual Trange get_trange() const = 0; /// Set the level to be matched virtual void set_trange(const Trange& trange) = 0; /// Clear the contents of the query, making it match all data virtual void clear() = 0; /** * Return true if this query matches a subset of the given query. * * In other words, it returns true if this query is the same as \a other, * plus zero or more extra fields set, or zero or more ranges narrowed. */ virtual bool is_subquery(const Query& other) const = 0; /** * Generate a sequence of key names and unique_ptr for all the * contents of the query */ virtual void foreach_key(std::function dest) const = 0; /// Print the query contents to stderr virtual void print(FILE* out) const = 0; /// Return a copy of this query virtual std::unique_ptr clone() const = 0; /// Create a new Query static std::unique_ptr create(); /// Create a new Query static std::unique_ptr from_record(const Record& rec); }; } #endif dballe-7.7/dballe/main-db.dox0000644000175000017500000000314412652630043013004 00000000000000/** @mainpage The DB-All.e db library \section db The DB-All.e database library This library contains all the functions to work with the main DB-All.e database. It includes both insert and query functions (see @ref db.h) and import/export functions (see @ref import.h and @ref export.h) to and from ::dba_msg structures. \section msg The DB-All.e msg library This library provides and encoding-independent message abstraction (see @ref msg.h and @ref msgs.h), and functions to intepret AOF, BUFR and CREX messages as physical information (see @ref bufrex_codec.h and @ref aof_codec.h). from the DB-All.e bufrex module, one main header file, @ref msg.h, which provides a container for parsed BUFR and CREX data and the BUFR and CREX encoding and decoding functions. The library also provides import/export functions from bufr, crex and aof, and to bufr and crex formats: see @ref bufrex_codec.h and @ref aof_codec.h \section bufrex The DB-All.e BUFR and CREX library This library provides BUFR and CREX encoding and decoding functions. There is only one main header file, @ref msg.h, which provides a container for parsed BUFR and CREX data and the BUFR and CREX encoding and decoding functions. \section core The DB-All.e core library This library provides various core functionality for weather applications. You can use it for: \li The infrastructure for error handling (see @ref error.h) \li The infrastructure for working with physical quantities (see @ref var.h, @ref vartable.h, @ref conv.h, @ref record.h) \li The infrastructure for reading and writing meteorological data (see @ref file.h, @ref rawmsg.h) */ dballe-7.7/dballe/Makefile.in0000644000175000017500000024646212652630066013047 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @FILE_OFFSET_BITS_64_TRUE@am__append_1 = -D_FILE_OFFSET_BITS=64 noinst_PROGRAMS = bench-run$(EXEEXT) dump-core-info$(EXEEXT) EXTRA_PROGRAMS = @HAVE_LIBPQ_TRUE@am__append_2 = \ @HAVE_LIBPQ_TRUE@ db/postgresql/internals.h \ @HAVE_LIBPQ_TRUE@ db/postgresql/repinfo.h \ @HAVE_LIBPQ_TRUE@ db/postgresql/station.h \ @HAVE_LIBPQ_TRUE@ db/postgresql/levtr.h \ @HAVE_LIBPQ_TRUE@ db/postgresql/datav6.h \ @HAVE_LIBPQ_TRUE@ db/postgresql/attrv6.h \ @HAVE_LIBPQ_TRUE@ db/postgresql/driver.h @HAVE_MYSQL_TRUE@am__append_3 = \ @HAVE_MYSQL_TRUE@ db/mysql/internals.h \ @HAVE_MYSQL_TRUE@ db/mysql/repinfo.h \ @HAVE_MYSQL_TRUE@ db/mysql/station.h \ @HAVE_MYSQL_TRUE@ db/mysql/levtr.h \ @HAVE_MYSQL_TRUE@ db/mysql/datav6.h \ @HAVE_MYSQL_TRUE@ db/mysql/attrv6.h \ @HAVE_MYSQL_TRUE@ db/mysql/driver.h @HAVE_ODBC_TRUE@am__append_4 = \ @HAVE_ODBC_TRUE@ db/odbc/internals.h \ @HAVE_ODBC_TRUE@ db/odbc/repinfo.h \ @HAVE_ODBC_TRUE@ db/odbc/station.h \ @HAVE_ODBC_TRUE@ db/odbc/levtr.h \ @HAVE_ODBC_TRUE@ db/odbc/datav6.h \ @HAVE_ODBC_TRUE@ db/odbc/attrv6.h \ @HAVE_ODBC_TRUE@ db/odbc/driver.h @HAVE_LIBPQ_TRUE@am__append_5 = \ @HAVE_LIBPQ_TRUE@ db/postgresql/internals.cc \ @HAVE_LIBPQ_TRUE@ db/postgresql/repinfo.cc \ @HAVE_LIBPQ_TRUE@ db/postgresql/station.cc \ @HAVE_LIBPQ_TRUE@ db/postgresql/levtr.cc \ @HAVE_LIBPQ_TRUE@ db/postgresql/datav6.cc \ @HAVE_LIBPQ_TRUE@ db/postgresql/attrv6.cc \ @HAVE_LIBPQ_TRUE@ db/postgresql/driver.cc @HAVE_MYSQL_TRUE@am__append_6 = \ @HAVE_MYSQL_TRUE@ db/mysql/internals.cc \ @HAVE_MYSQL_TRUE@ db/mysql/driver.cc \ @HAVE_MYSQL_TRUE@ db/mysql/repinfo.cc \ @HAVE_MYSQL_TRUE@ db/mysql/station.cc \ @HAVE_MYSQL_TRUE@ db/mysql/levtr.cc \ @HAVE_MYSQL_TRUE@ db/mysql/datav6.cc \ @HAVE_MYSQL_TRUE@ db/mysql/attrv6.cc @HAVE_ODBC_TRUE@am__append_7 = \ @HAVE_ODBC_TRUE@ db/odbc/internals.cc \ @HAVE_ODBC_TRUE@ db/odbc/repinfo.cc \ @HAVE_ODBC_TRUE@ db/odbc/station.cc \ @HAVE_ODBC_TRUE@ db/odbc/levtr.cc \ @HAVE_ODBC_TRUE@ db/odbc/datav6.cc \ @HAVE_ODBC_TRUE@ db/odbc/attrv6.cc \ @HAVE_ODBC_TRUE@ db/odbc/driver.cc check_PROGRAMS = test-dballe$(EXEEXT) @LUA_TRUE@am__append_8 = \ @LUA_TRUE@ msg/lua-test.cc \ @LUA_TRUE@ msg/tests-lua.cc @HAVE_LIBPQ_TRUE@am__append_9 = \ @HAVE_LIBPQ_TRUE@ db/postgresql/internals-test.cc @HAVE_MYSQL_TRUE@am__append_10 = \ @HAVE_MYSQL_TRUE@ db/mysql/internals-test.cc @HAVE_ODBC_TRUE@am__append_11 = \ @HAVE_ODBC_TRUE@ db/odbc/internals-test.cc subdir = dballe ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/m4_ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(dist_noinst_HEADERS) \ $(am__nobase_dist_dballeinclude_HEADERS_DIST) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" \ "$(DESTDIR)$(dballeincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libdballe_la_LIBADD = am__libdballe_la_SOURCES_DIST = file.cc message.cc types.cc record.cc \ query.cc var.cc core/verbose.cc core/aliases.cc \ core/aliases-reverse.cc core/defs.cc core/var.cc \ core/values.cc core/file.cc core/arrayfile.cc core/aoffile.cc \ core/csv.cc core/record_keyword.cc core/record.cc \ core/query.cc core/structbuf.cc core/matcher.cc \ core/match-wreport.cc core/varmatch.cc core/json.cc \ memdb/station.cc memdb/valuebase.cc memdb/stationvalue.cc \ memdb/levtr.cc memdb/valuestorage.cc memdb/index.cc \ memdb/match.cc memdb/results.cc memdb/value.cc memdb/memdb.cc \ memdb/serializer.cc msg/bulletin.cc msg/vars.cc msg/context.cc \ msg/msg.cc msg/msg-lua.cc msg/codec.cc msg/aof_codec.cc \ msg/aof_importers/common.cc msg/aof_importers/synop.cc \ msg/aof_importers/dribu.cc msg/aof_importers/flight.cc \ msg/aof_importers/temp.cc msg/aof_importers/pilot.cc \ msg/wr_codec.cc msg/wr_importers/base.cc \ msg/wr_importers/synop.cc msg/wr_importers/ship.cc \ msg/wr_importers/temp.cc msg/wr_importers/metar.cc \ msg/wr_importers/flight.cc msg/wr_importers/generic.cc \ msg/wr_importers/pollution.cc msg/wr_exporters/common.cc \ msg/wr_exporters/synop.cc msg/wr_exporters/ship.cc \ msg/wr_exporters/buoy.cc msg/wr_exporters/metar.cc \ msg/wr_exporters/temp.cc msg/wr_exporters/flight.cc \ msg/wr_exporters/generic.cc msg/wr_exporters/pollution.cc \ db/db.cc db/trace.cc db/querybuf.cc db/sql.cc \ db/sql/repinfo.cc db/sql/station.cc db/sql/levtr.cc \ db/sql/datav6.cc db/sql/attrv6.cc db/sql/driver.cc \ db/sqlite/internals.cc db/sqlite/repinfo.cc \ db/sqlite/station.cc db/sqlite/levtr.cc db/sqlite/datav6.cc \ db/sqlite/attrv6.cc db/sqlite/driver.cc db/mem/repinfo.cc \ db/mem/cursor.cc db/mem/db.cc db/v6/db.cc db/v6/cursor.cc \ db/v6/qbuilder.cc db/v6/import.cc db/v6/export.cc \ db/summary.cc cmdline/cmdline.cc cmdline/processor.cc \ cmdline/conversion.cc cmdline/dbadb.cc simple/simple.cc \ simple/commonapi.cc simple/msgapi.cc simple/dbapi.cc \ db/postgresql/internals.cc db/postgresql/repinfo.cc \ db/postgresql/station.cc db/postgresql/levtr.cc \ db/postgresql/datav6.cc db/postgresql/attrv6.cc \ db/postgresql/driver.cc db/mysql/internals.cc \ db/mysql/driver.cc db/mysql/repinfo.cc db/mysql/station.cc \ db/mysql/levtr.cc db/mysql/datav6.cc db/mysql/attrv6.cc \ db/odbc/internals.cc db/odbc/repinfo.cc db/odbc/station.cc \ db/odbc/levtr.cc db/odbc/datav6.cc db/odbc/attrv6.cc \ db/odbc/driver.cc am__dirstamp = $(am__leading_dot)dirstamp @HAVE_LIBPQ_TRUE@am__objects_1 = db/postgresql/internals.lo \ @HAVE_LIBPQ_TRUE@ db/postgresql/repinfo.lo \ @HAVE_LIBPQ_TRUE@ db/postgresql/station.lo \ @HAVE_LIBPQ_TRUE@ db/postgresql/levtr.lo \ @HAVE_LIBPQ_TRUE@ db/postgresql/datav6.lo \ @HAVE_LIBPQ_TRUE@ db/postgresql/attrv6.lo \ @HAVE_LIBPQ_TRUE@ db/postgresql/driver.lo @HAVE_MYSQL_TRUE@am__objects_2 = db/mysql/internals.lo \ @HAVE_MYSQL_TRUE@ db/mysql/driver.lo db/mysql/repinfo.lo \ @HAVE_MYSQL_TRUE@ db/mysql/station.lo db/mysql/levtr.lo \ @HAVE_MYSQL_TRUE@ db/mysql/datav6.lo db/mysql/attrv6.lo @HAVE_ODBC_TRUE@am__objects_3 = db/odbc/internals.lo \ @HAVE_ODBC_TRUE@ db/odbc/repinfo.lo db/odbc/station.lo \ @HAVE_ODBC_TRUE@ db/odbc/levtr.lo db/odbc/datav6.lo \ @HAVE_ODBC_TRUE@ db/odbc/attrv6.lo db/odbc/driver.lo am_libdballe_la_OBJECTS = file.lo message.lo types.lo record.lo \ query.lo var.lo core/verbose.lo core/aliases.lo \ core/aliases-reverse.lo core/defs.lo core/var.lo \ core/values.lo core/file.lo core/arrayfile.lo core/aoffile.lo \ core/csv.lo core/record_keyword.lo core/record.lo \ core/query.lo core/structbuf.lo core/matcher.lo \ core/match-wreport.lo core/varmatch.lo core/json.lo \ memdb/station.lo memdb/valuebase.lo memdb/stationvalue.lo \ memdb/levtr.lo memdb/valuestorage.lo memdb/index.lo \ memdb/match.lo memdb/results.lo memdb/value.lo memdb/memdb.lo \ memdb/serializer.lo msg/bulletin.lo msg/vars.lo msg/context.lo \ msg/msg.lo msg/msg-lua.lo msg/codec.lo msg/aof_codec.lo \ msg/aof_importers/common.lo msg/aof_importers/synop.lo \ msg/aof_importers/dribu.lo msg/aof_importers/flight.lo \ msg/aof_importers/temp.lo msg/aof_importers/pilot.lo \ msg/wr_codec.lo msg/wr_importers/base.lo \ msg/wr_importers/synop.lo msg/wr_importers/ship.lo \ msg/wr_importers/temp.lo msg/wr_importers/metar.lo \ msg/wr_importers/flight.lo msg/wr_importers/generic.lo \ msg/wr_importers/pollution.lo msg/wr_exporters/common.lo \ msg/wr_exporters/synop.lo msg/wr_exporters/ship.lo \ msg/wr_exporters/buoy.lo msg/wr_exporters/metar.lo \ msg/wr_exporters/temp.lo msg/wr_exporters/flight.lo \ msg/wr_exporters/generic.lo msg/wr_exporters/pollution.lo \ db/db.lo db/trace.lo db/querybuf.lo db/sql.lo \ db/sql/repinfo.lo db/sql/station.lo db/sql/levtr.lo \ db/sql/datav6.lo db/sql/attrv6.lo db/sql/driver.lo \ db/sqlite/internals.lo db/sqlite/repinfo.lo \ db/sqlite/station.lo db/sqlite/levtr.lo db/sqlite/datav6.lo \ db/sqlite/attrv6.lo db/sqlite/driver.lo db/mem/repinfo.lo \ db/mem/cursor.lo db/mem/db.lo db/v6/db.lo db/v6/cursor.lo \ db/v6/qbuilder.lo db/v6/import.lo db/v6/export.lo \ db/summary.lo cmdline/cmdline.lo cmdline/processor.lo \ cmdline/conversion.lo cmdline/dbadb.lo simple/simple.lo \ simple/commonapi.lo simple/msgapi.lo simple/dbapi.lo \ $(am__objects_1) $(am__objects_2) $(am__objects_3) libdballe_la_OBJECTS = $(am_libdballe_la_OBJECTS) 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 = libdballe_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(libdballe_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(noinst_PROGRAMS) am_bench_run_OBJECTS = db/db-query-parse-bench.$(OBJEXT) \ db/db-import-bench.$(OBJEXT) db/db-query-bench.$(OBJEXT) \ benchmark/bench-main.$(OBJEXT) bench_run_OBJECTS = $(am_bench_run_OBJECTS) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) bench_run_DEPENDENCIES = libdballe.la $(am__DEPENDENCIES_2) am_dump_core_info_OBJECTS = core/dump-core-info.$(OBJEXT) dump_core_info_OBJECTS = $(am_dump_core_info_OBJECTS) dump_core_info_DEPENDENCIES = libdballe.la $(am__DEPENDENCIES_2) am__test_dballe_SOURCES_DIST = tests-main.cc core/tests.cc \ file-test.cc message-test.cc types-test.cc record-test.cc \ query-test.cc var-test.cc core/aliases-test.cc \ core/stlutils-test.cc core/defs-test.cc core/var-test.cc \ core/values-test.cc core/file-test.cc core/record-test.cc \ core/query-test.cc core/structbuf-test.cc core/csv-test.cc \ core/matcher-test.cc core/match-wreport-test.cc \ core/varmatch-test.cc core/json-test.cc memdb/tests.cc \ memdb/valuestorage-test.cc memdb/index-test.cc \ memdb/match-test.cc memdb/results-test.cc \ memdb/station-test.cc memdb/valuebase-test.cc \ memdb/stationvalue-test.cc memdb/levtr-test.cc \ memdb/value-test.cc memdb/memdb-test.cc \ memdb/serializer-test.cc msg/tests.cc msg/bulletin-test.cc \ msg/vars-test.cc msg/context-test.cc msg/codec-test.cc \ msg/msg-test.cc msg/wr_codec_generic-test.cc \ msg/wr_codec-test.cc msg/wr_import-test.cc \ msg/wr_export-test.cc msg/aof_codec-test.cc db/tests.cc \ db/querybuf-test.cc db/trace-test.cc db/sql/repinfo-test.cc \ db/sql/station-test.cc db/sql/levtr-test.cc \ db/sql/datav6-test.cc db/sql/attrv6-test.cc \ db/sqlite/internals-test.cc db/db-basic-test.cc \ db/db-misc-test.cc db/db-query-station-test.cc \ db/db-query-data-test.cc db/db-query-summary-test.cc \ db/db-import-test.cc db/db-export-test.cc \ db/mem/repinfo-test.cc db/mem/cursor-test.cc \ db/summary-test.cc simple/msgapi-test.cc cmdline/dbadb-test.cc \ simple/dbapi-test.cc msg/lua-test.cc msg/tests-lua.cc \ db/postgresql/internals-test.cc db/mysql/internals-test.cc \ db/odbc/internals-test.cc @LUA_TRUE@am__objects_4 = msg/lua-test.$(OBJEXT) \ @LUA_TRUE@ msg/tests-lua.$(OBJEXT) @HAVE_LIBPQ_TRUE@am__objects_5 = \ @HAVE_LIBPQ_TRUE@ db/postgresql/internals-test.$(OBJEXT) @HAVE_MYSQL_TRUE@am__objects_6 = db/mysql/internals-test.$(OBJEXT) @HAVE_ODBC_TRUE@am__objects_7 = db/odbc/internals-test.$(OBJEXT) am_test_dballe_OBJECTS = tests-main.$(OBJEXT) core/tests.$(OBJEXT) \ file-test.$(OBJEXT) message-test.$(OBJEXT) \ types-test.$(OBJEXT) record-test.$(OBJEXT) \ query-test.$(OBJEXT) var-test.$(OBJEXT) \ core/aliases-test.$(OBJEXT) core/stlutils-test.$(OBJEXT) \ core/defs-test.$(OBJEXT) core/var-test.$(OBJEXT) \ core/values-test.$(OBJEXT) core/file-test.$(OBJEXT) \ core/record-test.$(OBJEXT) core/query-test.$(OBJEXT) \ core/structbuf-test.$(OBJEXT) core/csv-test.$(OBJEXT) \ core/matcher-test.$(OBJEXT) core/match-wreport-test.$(OBJEXT) \ core/varmatch-test.$(OBJEXT) core/json-test.$(OBJEXT) \ memdb/tests.$(OBJEXT) memdb/valuestorage-test.$(OBJEXT) \ memdb/index-test.$(OBJEXT) memdb/match-test.$(OBJEXT) \ memdb/results-test.$(OBJEXT) memdb/station-test.$(OBJEXT) \ memdb/valuebase-test.$(OBJEXT) \ memdb/stationvalue-test.$(OBJEXT) memdb/levtr-test.$(OBJEXT) \ memdb/value-test.$(OBJEXT) memdb/memdb-test.$(OBJEXT) \ memdb/serializer-test.$(OBJEXT) msg/tests.$(OBJEXT) \ msg/bulletin-test.$(OBJEXT) msg/vars-test.$(OBJEXT) \ msg/context-test.$(OBJEXT) msg/codec-test.$(OBJEXT) \ msg/msg-test.$(OBJEXT) msg/wr_codec_generic-test.$(OBJEXT) \ msg/wr_codec-test.$(OBJEXT) msg/wr_import-test.$(OBJEXT) \ msg/wr_export-test.$(OBJEXT) msg/aof_codec-test.$(OBJEXT) \ db/tests.$(OBJEXT) db/querybuf-test.$(OBJEXT) \ db/trace-test.$(OBJEXT) db/sql/repinfo-test.$(OBJEXT) \ db/sql/station-test.$(OBJEXT) db/sql/levtr-test.$(OBJEXT) \ db/sql/datav6-test.$(OBJEXT) db/sql/attrv6-test.$(OBJEXT) \ db/sqlite/internals-test.$(OBJEXT) db/db-basic-test.$(OBJEXT) \ db/db-misc-test.$(OBJEXT) db/db-query-station-test.$(OBJEXT) \ db/db-query-data-test.$(OBJEXT) \ db/db-query-summary-test.$(OBJEXT) db/db-import-test.$(OBJEXT) \ db/db-export-test.$(OBJEXT) db/mem/repinfo-test.$(OBJEXT) \ db/mem/cursor-test.$(OBJEXT) db/summary-test.$(OBJEXT) \ simple/msgapi-test.$(OBJEXT) cmdline/dbadb-test.$(OBJEXT) \ simple/dbapi-test.$(OBJEXT) $(am__objects_4) $(am__objects_5) \ $(am__objects_6) $(am__objects_7) test_dballe_OBJECTS = $(am_test_dballe_OBJECTS) test_dballe_DEPENDENCIES = libdballe.la $(am__DEPENDENCIES_2) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libdballe_la_SOURCES) $(bench_run_SOURCES) \ $(dump_core_info_SOURCES) $(test_dballe_SOURCES) DIST_SOURCES = $(am__libdballe_la_SOURCES_DIST) $(bench_run_SOURCES) \ $(dump_core_info_SOURCES) $(am__test_dballe_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(noinst_DATA) am__nobase_dist_dballeinclude_HEADERS_DIST = file.h message.h types.h \ record.h query.h var.h core/aliases.h core/verbose.h \ core/stlutils.h core/stlutils.tcc core/defs.h core/var.h \ core/values.h core/file.h core/arrayfile.h core/aoffile.h \ core/csv.h core/record.h core/query.h core/structbuf.h \ core/matcher.h core/match-wreport.h core/varmatch.h \ core/trace.h core/json.h memdb/valuestorage.h \ memdb/valuestorage.tcc memdb/index.h memdb/match.h \ memdb/match.tcc memdb/results.h memdb/results.tcc \ memdb/station.h memdb/valuebase.h memdb/stationvalue.h \ memdb/levtr.h memdb/value.h memdb/memdb.h memdb/serializer.h \ msg/codec.h msg/bulletin.h msg/context.h msg/vars.h msg/msg.h \ msg/msg-extravars.h msg/context-extravars.h msg/aof_codec.h \ msg/wr_codec.h msg/wr_exporters/common.h db/defs.h db/db.h \ db/trace.h db/mem/repinfo.h db/mem/cursor.h db/mem/db.h \ db/querybuf.h db/sql.h db/sql/internals.h db/sql/repinfo.h \ db/sql/station.h db/sql/levtr.h db/sql/datav6.h \ db/sql/attrv6.h db/sql/driver.h db/sqlite/internals.h \ db/sqlite/repinfo.h db/sqlite/station.h db/sqlite/levtr.h \ db/sqlite/datav6.h db/sqlite/attrv6.h db/sqlite/driver.h \ db/v6/db.h db/v6/cursor.h db/v6/qbuilder.h db/summary.h \ cmdline/cmdline.h cmdline/conversion.h cmdline/processor.h \ cmdline/dbadb.h simple/dbapi.h simple/simple.h \ simple/commonapi.h simple/msgapi.h db/postgresql/internals.h \ db/postgresql/repinfo.h db/postgresql/station.h \ db/postgresql/levtr.h db/postgresql/datav6.h \ db/postgresql/attrv6.h db/postgresql/driver.h \ db/mysql/internals.h db/mysql/repinfo.h db/mysql/station.h \ db/mysql/levtr.h db/mysql/datav6.h db/mysql/attrv6.h \ db/mysql/driver.h db/odbc/internals.h db/odbc/repinfo.h \ db/odbc/station.h db/odbc/levtr.h db/odbc/datav6.h \ db/odbc/attrv6.h db/odbc/driver.h HEADERS = $(dist_noinst_HEADERS) $(nobase_dist_dballeinclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FC = @FC@ FCFLAGS = @FCFLAGS@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDBALLEF_VERSION_INFO = @LIBDBALLEF_VERSION_INFO@ LIBDBALLE_VERSION_INFO = @LIBDBALLE_VERSION_INFO@ LIBOBJS = @LIBOBJS@ LIBPQ_CFLAGS = @LIBPQ_CFLAGS@ LIBPQ_LIBS = @LIBPQ_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ WREPORT_CFLAGS = @WREPORT_CFLAGS@ WREPORT_LIBS = @WREPORT_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_FC = @ac_ct_FC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_doxygen = @have_doxygen@ have_gperf = @have_gperf@ have_latex2html = @have_latex2html@ have_rst2html = @have_rst2html@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mysql_config = @mysql_config@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ tabledir = @tabledir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # filter.cc and sat.cc are here for now until I manage to turn them into a working system # toplevel EXTRA_DIST = core/aliases.gperf core/aliases.cc \ core/record_keyword.gperf core/record_keyword.cc msg/mkvars \ msg/vars.csv msg/vars.h msg/vars.gperf msg/vars.cc msg/vars.cc \ msg/msg-extravars.h msg/context-extravars.h core/vasprintf.h \ core/byteswap.h msg/wr_importers/base.h \ msg/aof_importers/common.h msg/filter.cc \ msg/wr_importers/sat.cc core/mkaliasdoc core/mkkeydoc \ msg/wr_exporters/exporters.dox msg/ltypes.txt msg/mklevels \ msg/mktranges mainpage.dox dballe.dox main-core.dox \ main-db.dox main-msg.dox CLEANFILES = core/aliases.dox core/aliases.tex core/record_keyword.dox \ core/record_keyword.dox core/record_keyword.rst \ core/record_keyword.tex msg/ltypes.dox msg/ltypes.tex \ msg/tranges.dox msg/tranges.tex AM_CPPFLAGS = -DTABLE_DIR=\"$(tabledir)\" -I$(top_srcdir) \ -I$(top_builddir) $(WREPORT_CFLAGS) $(LIBPQ_CFLAGS) \ $(SQLITE3_CFLAGS) $(MYSQL_CFLAGS) $(LUA_CFLAGS) \ $(am__append_1) common_libs = $(WREPORT_LIBS) $(LIBPQ_LIBS) $(SQLITE3_LIBS) $(MYSQL_LIBS) $(LUA_LIBS) BUILT_SOURCES = core/record_keyword.cc core/aliases.cc \ core/aliases-reverse.cc msg/vars.h msg/vars.cc msg/vars.gperf \ msg/msg-extravars.h msg/context-extravars.h # # Shared library # dballeincludedir = $(includedir)/dballe nobase_dist_dballeinclude_HEADERS = file.h message.h types.h record.h \ query.h var.h core/aliases.h core/verbose.h core/stlutils.h \ core/stlutils.tcc core/defs.h core/var.h core/values.h \ core/file.h core/arrayfile.h core/aoffile.h core/csv.h \ core/record.h core/query.h core/structbuf.h core/matcher.h \ core/match-wreport.h core/varmatch.h core/trace.h core/json.h \ memdb/valuestorage.h memdb/valuestorage.tcc memdb/index.h \ memdb/match.h memdb/match.tcc memdb/results.h \ memdb/results.tcc memdb/station.h memdb/valuebase.h \ memdb/stationvalue.h memdb/levtr.h memdb/value.h memdb/memdb.h \ memdb/serializer.h msg/codec.h msg/bulletin.h msg/context.h \ msg/vars.h msg/msg.h msg/msg-extravars.h \ msg/context-extravars.h msg/aof_codec.h msg/wr_codec.h \ msg/wr_exporters/common.h db/defs.h db/db.h db/trace.h \ db/mem/repinfo.h db/mem/cursor.h db/mem/db.h db/querybuf.h \ db/sql.h db/sql/internals.h db/sql/repinfo.h db/sql/station.h \ db/sql/levtr.h db/sql/datav6.h db/sql/attrv6.h db/sql/driver.h \ db/sqlite/internals.h db/sqlite/repinfo.h db/sqlite/station.h \ db/sqlite/levtr.h db/sqlite/datav6.h db/sqlite/attrv6.h \ db/sqlite/driver.h db/v6/db.h db/v6/cursor.h db/v6/qbuilder.h \ db/summary.h cmdline/cmdline.h cmdline/conversion.h \ cmdline/processor.h cmdline/dbadb.h simple/dbapi.h \ simple/simple.h simple/commonapi.h simple/msgapi.h \ $(am__append_2) $(am__append_3) $(am__append_4) lib_LTLIBRARIES = libdballe.la libdballe_la_SOURCES = file.cc message.cc types.cc record.cc query.cc \ var.cc core/verbose.cc core/aliases.cc core/aliases-reverse.cc \ core/defs.cc core/var.cc core/values.cc core/file.cc \ core/arrayfile.cc core/aoffile.cc core/csv.cc \ core/record_keyword.cc core/record.cc core/query.cc \ core/structbuf.cc core/matcher.cc core/match-wreport.cc \ core/varmatch.cc core/json.cc memdb/station.cc \ memdb/valuebase.cc memdb/stationvalue.cc memdb/levtr.cc \ memdb/valuestorage.cc memdb/index.cc memdb/match.cc \ memdb/results.cc memdb/value.cc memdb/memdb.cc \ memdb/serializer.cc msg/bulletin.cc msg/vars.cc msg/context.cc \ msg/msg.cc msg/msg-lua.cc msg/codec.cc msg/aof_codec.cc \ msg/aof_importers/common.cc msg/aof_importers/synop.cc \ msg/aof_importers/dribu.cc msg/aof_importers/flight.cc \ msg/aof_importers/temp.cc msg/aof_importers/pilot.cc \ msg/wr_codec.cc msg/wr_importers/base.cc \ msg/wr_importers/synop.cc msg/wr_importers/ship.cc \ msg/wr_importers/temp.cc msg/wr_importers/metar.cc \ msg/wr_importers/flight.cc msg/wr_importers/generic.cc \ msg/wr_importers/pollution.cc msg/wr_exporters/common.cc \ msg/wr_exporters/synop.cc msg/wr_exporters/ship.cc \ msg/wr_exporters/buoy.cc msg/wr_exporters/metar.cc \ msg/wr_exporters/temp.cc msg/wr_exporters/flight.cc \ msg/wr_exporters/generic.cc msg/wr_exporters/pollution.cc \ db/db.cc db/trace.cc db/querybuf.cc db/sql.cc \ db/sql/repinfo.cc db/sql/station.cc db/sql/levtr.cc \ db/sql/datav6.cc db/sql/attrv6.cc db/sql/driver.cc \ db/sqlite/internals.cc db/sqlite/repinfo.cc \ db/sqlite/station.cc db/sqlite/levtr.cc db/sqlite/datav6.cc \ db/sqlite/attrv6.cc db/sqlite/driver.cc db/mem/repinfo.cc \ db/mem/cursor.cc db/mem/db.cc db/v6/db.cc db/v6/cursor.cc \ db/v6/qbuilder.cc db/v6/import.cc db/v6/export.cc \ db/summary.cc cmdline/cmdline.cc cmdline/processor.cc \ cmdline/conversion.cc cmdline/dbadb.cc simple/simple.cc \ simple/commonapi.cc simple/msgapi.cc simple/dbapi.cc \ $(am__append_5) $(am__append_6) $(am__append_7) libdballe_la_LDFLAGS = -version-info @LIBDBALLE_VERSION_INFO@ $(common_libs) TESTS_ENVIRONMENT = $(top_srcdir)/extra/runtest #CXXFLAGS += -O0 dist_noinst_HEADERS = core/tests.h memdb/tests.h msg/tests.h \ msg/tests-lua.h db/tests.h db/bench.h test_dballe_SOURCES = tests-main.cc core/tests.cc file-test.cc \ message-test.cc types-test.cc record-test.cc query-test.cc \ var-test.cc core/aliases-test.cc core/stlutils-test.cc \ core/defs-test.cc core/var-test.cc core/values-test.cc \ core/file-test.cc core/record-test.cc core/query-test.cc \ core/structbuf-test.cc core/csv-test.cc core/matcher-test.cc \ core/match-wreport-test.cc core/varmatch-test.cc \ core/json-test.cc memdb/tests.cc memdb/valuestorage-test.cc \ memdb/index-test.cc memdb/match-test.cc memdb/results-test.cc \ memdb/station-test.cc memdb/valuebase-test.cc \ memdb/stationvalue-test.cc memdb/levtr-test.cc \ memdb/value-test.cc memdb/memdb-test.cc \ memdb/serializer-test.cc msg/tests.cc msg/bulletin-test.cc \ msg/vars-test.cc msg/context-test.cc msg/codec-test.cc \ msg/msg-test.cc msg/wr_codec_generic-test.cc \ msg/wr_codec-test.cc msg/wr_import-test.cc \ msg/wr_export-test.cc msg/aof_codec-test.cc db/tests.cc \ db/querybuf-test.cc db/trace-test.cc db/sql/repinfo-test.cc \ db/sql/station-test.cc db/sql/levtr-test.cc \ db/sql/datav6-test.cc db/sql/attrv6-test.cc \ db/sqlite/internals-test.cc db/db-basic-test.cc \ db/db-misc-test.cc db/db-query-station-test.cc \ db/db-query-data-test.cc db/db-query-summary-test.cc \ db/db-import-test.cc db/db-export-test.cc \ db/mem/repinfo-test.cc db/mem/cursor-test.cc \ db/summary-test.cc simple/msgapi-test.cc cmdline/dbadb-test.cc \ simple/dbapi-test.cc $(am__append_8) $(am__append_9) \ $(am__append_10) $(am__append_11) test_dballe_LDADD = \ libdballe.la \ $(common_libs) bench_run_SOURCES = \ db/db-query-parse-bench.cc \ db/db-import-bench.cc \ db/db-query-bench.cc \ benchmark/bench-main.cc bench_run_LDADD = \ libdballe.la \ $(common_libs) dump_core_info_SOURCES = core/dump-core-info.cc dump_core_info_LDADD = \ libdballe.la \ $(common_libs) # core # msg noinst_DATA = core/record_keyword.dox core/record_keyword.rst \ core/record_keyword.tex core/aliases.dox core/aliases.tex \ msg/ltypes.dox msg/ltypes.tex msg/tranges.dox msg/tranges.tex all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign dballe/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign dballe/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *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);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } core/$(am__dirstamp): @$(MKDIR_P) core @: > core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) core/$(DEPDIR) @: > core/$(DEPDIR)/$(am__dirstamp) core/verbose.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/aliases.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/aliases-reverse.lo: core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/defs.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/var.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/values.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/file.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/arrayfile.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/aoffile.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/csv.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/record_keyword.lo: core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/record.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/query.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/structbuf.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/matcher.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/match-wreport.lo: core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/varmatch.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) core/json.lo: core/$(am__dirstamp) core/$(DEPDIR)/$(am__dirstamp) memdb/$(am__dirstamp): @$(MKDIR_P) memdb @: > memdb/$(am__dirstamp) memdb/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) memdb/$(DEPDIR) @: > memdb/$(DEPDIR)/$(am__dirstamp) memdb/station.lo: memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/valuebase.lo: memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/stationvalue.lo: memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/levtr.lo: memdb/$(am__dirstamp) memdb/$(DEPDIR)/$(am__dirstamp) memdb/valuestorage.lo: memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/index.lo: memdb/$(am__dirstamp) memdb/$(DEPDIR)/$(am__dirstamp) memdb/match.lo: memdb/$(am__dirstamp) memdb/$(DEPDIR)/$(am__dirstamp) memdb/results.lo: memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/value.lo: memdb/$(am__dirstamp) memdb/$(DEPDIR)/$(am__dirstamp) memdb/memdb.lo: memdb/$(am__dirstamp) memdb/$(DEPDIR)/$(am__dirstamp) memdb/serializer.lo: memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) msg/$(am__dirstamp): @$(MKDIR_P) msg @: > msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) msg/$(DEPDIR) @: > msg/$(DEPDIR)/$(am__dirstamp) msg/bulletin.lo: msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp) msg/vars.lo: msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp) msg/context.lo: msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp) msg/msg.lo: msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp) msg/msg-lua.lo: msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp) msg/codec.lo: msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp) msg/aof_codec.lo: msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp) msg/aof_importers/$(am__dirstamp): @$(MKDIR_P) msg/aof_importers @: > msg/aof_importers/$(am__dirstamp) msg/aof_importers/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) msg/aof_importers/$(DEPDIR) @: > msg/aof_importers/$(DEPDIR)/$(am__dirstamp) msg/aof_importers/common.lo: msg/aof_importers/$(am__dirstamp) \ msg/aof_importers/$(DEPDIR)/$(am__dirstamp) msg/aof_importers/synop.lo: msg/aof_importers/$(am__dirstamp) \ msg/aof_importers/$(DEPDIR)/$(am__dirstamp) msg/aof_importers/dribu.lo: msg/aof_importers/$(am__dirstamp) \ msg/aof_importers/$(DEPDIR)/$(am__dirstamp) msg/aof_importers/flight.lo: msg/aof_importers/$(am__dirstamp) \ msg/aof_importers/$(DEPDIR)/$(am__dirstamp) msg/aof_importers/temp.lo: msg/aof_importers/$(am__dirstamp) \ msg/aof_importers/$(DEPDIR)/$(am__dirstamp) msg/aof_importers/pilot.lo: msg/aof_importers/$(am__dirstamp) \ msg/aof_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_codec.lo: msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp) msg/wr_importers/$(am__dirstamp): @$(MKDIR_P) msg/wr_importers @: > msg/wr_importers/$(am__dirstamp) msg/wr_importers/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) msg/wr_importers/$(DEPDIR) @: > msg/wr_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_importers/base.lo: msg/wr_importers/$(am__dirstamp) \ msg/wr_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_importers/synop.lo: msg/wr_importers/$(am__dirstamp) \ msg/wr_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_importers/ship.lo: msg/wr_importers/$(am__dirstamp) \ msg/wr_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_importers/temp.lo: msg/wr_importers/$(am__dirstamp) \ msg/wr_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_importers/metar.lo: msg/wr_importers/$(am__dirstamp) \ msg/wr_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_importers/flight.lo: msg/wr_importers/$(am__dirstamp) \ msg/wr_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_importers/generic.lo: msg/wr_importers/$(am__dirstamp) \ msg/wr_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_importers/pollution.lo: msg/wr_importers/$(am__dirstamp) \ msg/wr_importers/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/$(am__dirstamp): @$(MKDIR_P) msg/wr_exporters @: > msg/wr_exporters/$(am__dirstamp) msg/wr_exporters/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) msg/wr_exporters/$(DEPDIR) @: > msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/common.lo: msg/wr_exporters/$(am__dirstamp) \ msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/synop.lo: msg/wr_exporters/$(am__dirstamp) \ msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/ship.lo: msg/wr_exporters/$(am__dirstamp) \ msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/buoy.lo: msg/wr_exporters/$(am__dirstamp) \ msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/metar.lo: msg/wr_exporters/$(am__dirstamp) \ msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/temp.lo: msg/wr_exporters/$(am__dirstamp) \ msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/flight.lo: msg/wr_exporters/$(am__dirstamp) \ msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/generic.lo: msg/wr_exporters/$(am__dirstamp) \ msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) msg/wr_exporters/pollution.lo: msg/wr_exporters/$(am__dirstamp) \ msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) db/$(am__dirstamp): @$(MKDIR_P) db @: > db/$(am__dirstamp) db/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) db/$(DEPDIR) @: > db/$(DEPDIR)/$(am__dirstamp) db/db.lo: db/$(am__dirstamp) db/$(DEPDIR)/$(am__dirstamp) db/trace.lo: db/$(am__dirstamp) db/$(DEPDIR)/$(am__dirstamp) db/querybuf.lo: db/$(am__dirstamp) db/$(DEPDIR)/$(am__dirstamp) db/sql.lo: db/$(am__dirstamp) db/$(DEPDIR)/$(am__dirstamp) db/sql/$(am__dirstamp): @$(MKDIR_P) db/sql @: > db/sql/$(am__dirstamp) db/sql/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) db/sql/$(DEPDIR) @: > db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/repinfo.lo: db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/station.lo: db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/levtr.lo: db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/datav6.lo: db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/attrv6.lo: db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/driver.lo: db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sqlite/$(am__dirstamp): @$(MKDIR_P) db/sqlite @: > db/sqlite/$(am__dirstamp) db/sqlite/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) db/sqlite/$(DEPDIR) @: > db/sqlite/$(DEPDIR)/$(am__dirstamp) db/sqlite/internals.lo: db/sqlite/$(am__dirstamp) \ db/sqlite/$(DEPDIR)/$(am__dirstamp) db/sqlite/repinfo.lo: db/sqlite/$(am__dirstamp) \ db/sqlite/$(DEPDIR)/$(am__dirstamp) db/sqlite/station.lo: db/sqlite/$(am__dirstamp) \ db/sqlite/$(DEPDIR)/$(am__dirstamp) db/sqlite/levtr.lo: db/sqlite/$(am__dirstamp) \ db/sqlite/$(DEPDIR)/$(am__dirstamp) db/sqlite/datav6.lo: db/sqlite/$(am__dirstamp) \ db/sqlite/$(DEPDIR)/$(am__dirstamp) db/sqlite/attrv6.lo: db/sqlite/$(am__dirstamp) \ db/sqlite/$(DEPDIR)/$(am__dirstamp) db/sqlite/driver.lo: db/sqlite/$(am__dirstamp) \ db/sqlite/$(DEPDIR)/$(am__dirstamp) db/mem/$(am__dirstamp): @$(MKDIR_P) db/mem @: > db/mem/$(am__dirstamp) db/mem/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) db/mem/$(DEPDIR) @: > db/mem/$(DEPDIR)/$(am__dirstamp) db/mem/repinfo.lo: db/mem/$(am__dirstamp) \ db/mem/$(DEPDIR)/$(am__dirstamp) db/mem/cursor.lo: db/mem/$(am__dirstamp) \ db/mem/$(DEPDIR)/$(am__dirstamp) db/mem/db.lo: db/mem/$(am__dirstamp) db/mem/$(DEPDIR)/$(am__dirstamp) db/v6/$(am__dirstamp): @$(MKDIR_P) db/v6 @: > db/v6/$(am__dirstamp) db/v6/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) db/v6/$(DEPDIR) @: > db/v6/$(DEPDIR)/$(am__dirstamp) db/v6/db.lo: db/v6/$(am__dirstamp) db/v6/$(DEPDIR)/$(am__dirstamp) db/v6/cursor.lo: db/v6/$(am__dirstamp) db/v6/$(DEPDIR)/$(am__dirstamp) db/v6/qbuilder.lo: db/v6/$(am__dirstamp) \ db/v6/$(DEPDIR)/$(am__dirstamp) db/v6/import.lo: db/v6/$(am__dirstamp) db/v6/$(DEPDIR)/$(am__dirstamp) db/v6/export.lo: db/v6/$(am__dirstamp) db/v6/$(DEPDIR)/$(am__dirstamp) db/summary.lo: db/$(am__dirstamp) db/$(DEPDIR)/$(am__dirstamp) cmdline/$(am__dirstamp): @$(MKDIR_P) cmdline @: > cmdline/$(am__dirstamp) cmdline/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) cmdline/$(DEPDIR) @: > cmdline/$(DEPDIR)/$(am__dirstamp) cmdline/cmdline.lo: cmdline/$(am__dirstamp) \ cmdline/$(DEPDIR)/$(am__dirstamp) cmdline/processor.lo: cmdline/$(am__dirstamp) \ cmdline/$(DEPDIR)/$(am__dirstamp) cmdline/conversion.lo: cmdline/$(am__dirstamp) \ cmdline/$(DEPDIR)/$(am__dirstamp) cmdline/dbadb.lo: cmdline/$(am__dirstamp) \ cmdline/$(DEPDIR)/$(am__dirstamp) simple/$(am__dirstamp): @$(MKDIR_P) simple @: > simple/$(am__dirstamp) simple/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) simple/$(DEPDIR) @: > simple/$(DEPDIR)/$(am__dirstamp) simple/simple.lo: simple/$(am__dirstamp) \ simple/$(DEPDIR)/$(am__dirstamp) simple/commonapi.lo: simple/$(am__dirstamp) \ simple/$(DEPDIR)/$(am__dirstamp) simple/msgapi.lo: simple/$(am__dirstamp) \ simple/$(DEPDIR)/$(am__dirstamp) simple/dbapi.lo: simple/$(am__dirstamp) \ simple/$(DEPDIR)/$(am__dirstamp) db/postgresql/$(am__dirstamp): @$(MKDIR_P) db/postgresql @: > db/postgresql/$(am__dirstamp) db/postgresql/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) db/postgresql/$(DEPDIR) @: > db/postgresql/$(DEPDIR)/$(am__dirstamp) db/postgresql/internals.lo: db/postgresql/$(am__dirstamp) \ db/postgresql/$(DEPDIR)/$(am__dirstamp) db/postgresql/repinfo.lo: db/postgresql/$(am__dirstamp) \ db/postgresql/$(DEPDIR)/$(am__dirstamp) db/postgresql/station.lo: db/postgresql/$(am__dirstamp) \ db/postgresql/$(DEPDIR)/$(am__dirstamp) db/postgresql/levtr.lo: db/postgresql/$(am__dirstamp) \ db/postgresql/$(DEPDIR)/$(am__dirstamp) db/postgresql/datav6.lo: db/postgresql/$(am__dirstamp) \ db/postgresql/$(DEPDIR)/$(am__dirstamp) db/postgresql/attrv6.lo: db/postgresql/$(am__dirstamp) \ db/postgresql/$(DEPDIR)/$(am__dirstamp) db/postgresql/driver.lo: db/postgresql/$(am__dirstamp) \ db/postgresql/$(DEPDIR)/$(am__dirstamp) db/mysql/$(am__dirstamp): @$(MKDIR_P) db/mysql @: > db/mysql/$(am__dirstamp) db/mysql/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) db/mysql/$(DEPDIR) @: > db/mysql/$(DEPDIR)/$(am__dirstamp) db/mysql/internals.lo: db/mysql/$(am__dirstamp) \ db/mysql/$(DEPDIR)/$(am__dirstamp) db/mysql/driver.lo: db/mysql/$(am__dirstamp) \ db/mysql/$(DEPDIR)/$(am__dirstamp) db/mysql/repinfo.lo: db/mysql/$(am__dirstamp) \ db/mysql/$(DEPDIR)/$(am__dirstamp) db/mysql/station.lo: db/mysql/$(am__dirstamp) \ db/mysql/$(DEPDIR)/$(am__dirstamp) db/mysql/levtr.lo: db/mysql/$(am__dirstamp) \ db/mysql/$(DEPDIR)/$(am__dirstamp) db/mysql/datav6.lo: db/mysql/$(am__dirstamp) \ db/mysql/$(DEPDIR)/$(am__dirstamp) db/mysql/attrv6.lo: db/mysql/$(am__dirstamp) \ db/mysql/$(DEPDIR)/$(am__dirstamp) db/odbc/$(am__dirstamp): @$(MKDIR_P) db/odbc @: > db/odbc/$(am__dirstamp) db/odbc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) db/odbc/$(DEPDIR) @: > db/odbc/$(DEPDIR)/$(am__dirstamp) db/odbc/internals.lo: db/odbc/$(am__dirstamp) \ db/odbc/$(DEPDIR)/$(am__dirstamp) db/odbc/repinfo.lo: db/odbc/$(am__dirstamp) \ db/odbc/$(DEPDIR)/$(am__dirstamp) db/odbc/station.lo: db/odbc/$(am__dirstamp) \ db/odbc/$(DEPDIR)/$(am__dirstamp) db/odbc/levtr.lo: db/odbc/$(am__dirstamp) \ db/odbc/$(DEPDIR)/$(am__dirstamp) db/odbc/datav6.lo: db/odbc/$(am__dirstamp) \ db/odbc/$(DEPDIR)/$(am__dirstamp) db/odbc/attrv6.lo: db/odbc/$(am__dirstamp) \ db/odbc/$(DEPDIR)/$(am__dirstamp) db/odbc/driver.lo: db/odbc/$(am__dirstamp) \ db/odbc/$(DEPDIR)/$(am__dirstamp) libdballe.la: $(libdballe_la_OBJECTS) $(libdballe_la_DEPENDENCIES) $(EXTRA_libdballe_la_DEPENDENCIES) $(AM_V_CXXLD)$(libdballe_la_LINK) -rpath $(libdir) $(libdballe_la_OBJECTS) $(libdballe_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 clean-noinstPROGRAMS: @list='$(noinst_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 db/db-query-parse-bench.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/db-import-bench.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/db-query-bench.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) benchmark/$(am__dirstamp): @$(MKDIR_P) benchmark @: > benchmark/$(am__dirstamp) benchmark/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) benchmark/$(DEPDIR) @: > benchmark/$(DEPDIR)/$(am__dirstamp) benchmark/bench-main.$(OBJEXT): benchmark/$(am__dirstamp) \ benchmark/$(DEPDIR)/$(am__dirstamp) bench-run$(EXEEXT): $(bench_run_OBJECTS) $(bench_run_DEPENDENCIES) $(EXTRA_bench_run_DEPENDENCIES) @rm -f bench-run$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(bench_run_OBJECTS) $(bench_run_LDADD) $(LIBS) core/dump-core-info.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) dump-core-info$(EXEEXT): $(dump_core_info_OBJECTS) $(dump_core_info_DEPENDENCIES) $(EXTRA_dump_core_info_DEPENDENCIES) @rm -f dump-core-info$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(dump_core_info_OBJECTS) $(dump_core_info_LDADD) $(LIBS) core/tests.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/aliases-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/stlutils-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/defs-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/var-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/values-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/file-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/record-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/query-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/structbuf-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/csv-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/matcher-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/match-wreport-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/varmatch-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) core/json-test.$(OBJEXT): core/$(am__dirstamp) \ core/$(DEPDIR)/$(am__dirstamp) memdb/tests.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/valuestorage-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/index-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/match-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/results-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/station-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/valuebase-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/stationvalue-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/levtr-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/value-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/memdb-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) memdb/serializer-test.$(OBJEXT): memdb/$(am__dirstamp) \ memdb/$(DEPDIR)/$(am__dirstamp) msg/tests.$(OBJEXT): msg/$(am__dirstamp) msg/$(DEPDIR)/$(am__dirstamp) msg/bulletin-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/vars-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/context-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/codec-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/msg-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/wr_codec_generic-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/wr_codec-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/wr_import-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/wr_export-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/aof_codec-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) db/tests.$(OBJEXT): db/$(am__dirstamp) db/$(DEPDIR)/$(am__dirstamp) db/querybuf-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/trace-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/sql/repinfo-test.$(OBJEXT): db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/station-test.$(OBJEXT): db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/levtr-test.$(OBJEXT): db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/datav6-test.$(OBJEXT): db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sql/attrv6-test.$(OBJEXT): db/sql/$(am__dirstamp) \ db/sql/$(DEPDIR)/$(am__dirstamp) db/sqlite/internals-test.$(OBJEXT): db/sqlite/$(am__dirstamp) \ db/sqlite/$(DEPDIR)/$(am__dirstamp) db/db-basic-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/db-misc-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/db-query-station-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/db-query-data-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/db-query-summary-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/db-import-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/db-export-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) db/mem/repinfo-test.$(OBJEXT): db/mem/$(am__dirstamp) \ db/mem/$(DEPDIR)/$(am__dirstamp) db/mem/cursor-test.$(OBJEXT): db/mem/$(am__dirstamp) \ db/mem/$(DEPDIR)/$(am__dirstamp) db/summary-test.$(OBJEXT): db/$(am__dirstamp) \ db/$(DEPDIR)/$(am__dirstamp) simple/msgapi-test.$(OBJEXT): simple/$(am__dirstamp) \ simple/$(DEPDIR)/$(am__dirstamp) cmdline/dbadb-test.$(OBJEXT): cmdline/$(am__dirstamp) \ cmdline/$(DEPDIR)/$(am__dirstamp) simple/dbapi-test.$(OBJEXT): simple/$(am__dirstamp) \ simple/$(DEPDIR)/$(am__dirstamp) msg/lua-test.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) msg/tests-lua.$(OBJEXT): msg/$(am__dirstamp) \ msg/$(DEPDIR)/$(am__dirstamp) db/postgresql/internals-test.$(OBJEXT): db/postgresql/$(am__dirstamp) \ db/postgresql/$(DEPDIR)/$(am__dirstamp) db/mysql/internals-test.$(OBJEXT): db/mysql/$(am__dirstamp) \ db/mysql/$(DEPDIR)/$(am__dirstamp) db/odbc/internals-test.$(OBJEXT): db/odbc/$(am__dirstamp) \ db/odbc/$(DEPDIR)/$(am__dirstamp) test-dballe$(EXEEXT): $(test_dballe_OBJECTS) $(test_dballe_DEPENDENCIES) $(EXTRA_test_dballe_DEPENDENCIES) @rm -f test-dballe$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_dballe_OBJECTS) $(test_dballe_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f benchmark/*.$(OBJEXT) -rm -f cmdline/*.$(OBJEXT) -rm -f cmdline/*.lo -rm -f core/*.$(OBJEXT) -rm -f core/*.lo -rm -f db/*.$(OBJEXT) -rm -f db/*.lo -rm -f db/mem/*.$(OBJEXT) -rm -f db/mem/*.lo -rm -f db/mysql/*.$(OBJEXT) -rm -f db/mysql/*.lo -rm -f db/odbc/*.$(OBJEXT) -rm -f db/odbc/*.lo -rm -f db/postgresql/*.$(OBJEXT) -rm -f db/postgresql/*.lo -rm -f db/sql/*.$(OBJEXT) -rm -f db/sql/*.lo -rm -f db/sqlite/*.$(OBJEXT) -rm -f db/sqlite/*.lo -rm -f db/v6/*.$(OBJEXT) -rm -f db/v6/*.lo -rm -f memdb/*.$(OBJEXT) -rm -f memdb/*.lo -rm -f msg/*.$(OBJEXT) -rm -f msg/*.lo -rm -f msg/aof_importers/*.$(OBJEXT) -rm -f msg/aof_importers/*.lo -rm -f msg/wr_exporters/*.$(OBJEXT) -rm -f msg/wr_exporters/*.lo -rm -f msg/wr_importers/*.$(OBJEXT) -rm -f msg/wr_importers/*.lo -rm -f simple/*.$(OBJEXT) -rm -f simple/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/query-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/query.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/record-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/record.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/types-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/types.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@benchmark/$(DEPDIR)/bench-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@cmdline/$(DEPDIR)/cmdline.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@cmdline/$(DEPDIR)/conversion.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@cmdline/$(DEPDIR)/dbadb-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@cmdline/$(DEPDIR)/dbadb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@cmdline/$(DEPDIR)/processor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/aliases-reverse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/aliases-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/aliases.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/aoffile.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/arrayfile.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/csv-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/csv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/defs-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/defs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/dump-core-info.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/file-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/json-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/json.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/match-wreport-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/match-wreport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/matcher-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/matcher.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/query-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/query.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/record-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/record.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/record_keyword.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/stlutils-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/structbuf-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/structbuf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/tests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/values-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/values.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/var-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/var.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/varmatch-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/varmatch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@core/$(DEPDIR)/verbose.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-basic-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-export-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-import-bench.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-import-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-misc-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-query-bench.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-query-data-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-query-parse-bench.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-query-station-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db-query-summary-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/db.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/querybuf-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/querybuf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/sql.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/summary-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/summary.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/tests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/trace-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/$(DEPDIR)/trace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mem/$(DEPDIR)/cursor-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mem/$(DEPDIR)/cursor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mem/$(DEPDIR)/db.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mem/$(DEPDIR)/repinfo-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mem/$(DEPDIR)/repinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mysql/$(DEPDIR)/attrv6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mysql/$(DEPDIR)/datav6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mysql/$(DEPDIR)/driver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mysql/$(DEPDIR)/internals-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mysql/$(DEPDIR)/internals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mysql/$(DEPDIR)/levtr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mysql/$(DEPDIR)/repinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/mysql/$(DEPDIR)/station.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/odbc/$(DEPDIR)/attrv6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/odbc/$(DEPDIR)/datav6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/odbc/$(DEPDIR)/driver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/odbc/$(DEPDIR)/internals-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/odbc/$(DEPDIR)/internals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/odbc/$(DEPDIR)/levtr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/odbc/$(DEPDIR)/repinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/odbc/$(DEPDIR)/station.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/postgresql/$(DEPDIR)/attrv6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/postgresql/$(DEPDIR)/datav6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/postgresql/$(DEPDIR)/driver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/postgresql/$(DEPDIR)/internals-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/postgresql/$(DEPDIR)/internals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/postgresql/$(DEPDIR)/levtr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/postgresql/$(DEPDIR)/repinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/postgresql/$(DEPDIR)/station.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/attrv6-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/attrv6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/datav6-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/datav6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/driver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/levtr-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/levtr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/repinfo-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/repinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/station-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sql/$(DEPDIR)/station.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sqlite/$(DEPDIR)/attrv6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sqlite/$(DEPDIR)/datav6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sqlite/$(DEPDIR)/driver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sqlite/$(DEPDIR)/internals-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sqlite/$(DEPDIR)/internals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sqlite/$(DEPDIR)/levtr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sqlite/$(DEPDIR)/repinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/sqlite/$(DEPDIR)/station.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/v6/$(DEPDIR)/cursor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/v6/$(DEPDIR)/db.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/v6/$(DEPDIR)/export.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/v6/$(DEPDIR)/import.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@db/v6/$(DEPDIR)/qbuilder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/index-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/index.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/levtr-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/levtr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/match-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/match.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/memdb-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/memdb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/results-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/results.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/serializer-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/serializer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/station-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/station.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/stationvalue-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/stationvalue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/tests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/value-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/value.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/valuebase-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/valuebase.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/valuestorage-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@memdb/$(DEPDIR)/valuestorage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/aof_codec-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/aof_codec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/bulletin-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/bulletin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/codec-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/codec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/context-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/context.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/lua-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/msg-lua.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/msg-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/msg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/tests-lua.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/tests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/vars-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/vars.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/wr_codec-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/wr_codec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/wr_codec_generic-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/wr_export-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/$(DEPDIR)/wr_import-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/aof_importers/$(DEPDIR)/common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/aof_importers/$(DEPDIR)/dribu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/aof_importers/$(DEPDIR)/flight.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/aof_importers/$(DEPDIR)/pilot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/aof_importers/$(DEPDIR)/synop.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/aof_importers/$(DEPDIR)/temp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_exporters/$(DEPDIR)/buoy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_exporters/$(DEPDIR)/common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_exporters/$(DEPDIR)/flight.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_exporters/$(DEPDIR)/generic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_exporters/$(DEPDIR)/metar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_exporters/$(DEPDIR)/pollution.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_exporters/$(DEPDIR)/ship.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_exporters/$(DEPDIR)/synop.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_exporters/$(DEPDIR)/temp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_importers/$(DEPDIR)/base.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_importers/$(DEPDIR)/flight.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_importers/$(DEPDIR)/generic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_importers/$(DEPDIR)/metar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_importers/$(DEPDIR)/pollution.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_importers/$(DEPDIR)/ship.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_importers/$(DEPDIR)/synop.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msg/wr_importers/$(DEPDIR)/temp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@simple/$(DEPDIR)/commonapi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@simple/$(DEPDIR)/dbapi-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@simple/$(DEPDIR)/dbapi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@simple/$(DEPDIR)/msgapi-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@simple/$(DEPDIR)/msgapi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@simple/$(DEPDIR)/simple.Plo@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf cmdline/.libs cmdline/_libs -rm -rf core/.libs core/_libs -rm -rf db/.libs db/_libs -rm -rf db/mem/.libs db/mem/_libs -rm -rf db/mysql/.libs db/mysql/_libs -rm -rf db/odbc/.libs db/odbc/_libs -rm -rf db/postgresql/.libs db/postgresql/_libs -rm -rf db/sql/.libs db/sql/_libs -rm -rf db/sqlite/.libs db/sqlite/_libs -rm -rf db/v6/.libs db/v6/_libs -rm -rf memdb/.libs memdb/_libs -rm -rf msg/.libs msg/_libs -rm -rf msg/aof_importers/.libs msg/aof_importers/_libs -rm -rf msg/wr_exporters/.libs msg/wr_exporters/_libs -rm -rf msg/wr_importers/.libs msg/wr_importers/_libs -rm -rf simple/.libs simple/_libs install-nobase_dist_dballeincludeHEADERS: $(nobase_dist_dballeinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_dist_dballeinclude_HEADERS)'; test -n "$(dballeincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(dballeincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(dballeincludedir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(dballeincludedir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(dballeincludedir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(dballeincludedir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(dballeincludedir)/$$dir" || exit $$?; }; \ done uninstall-nobase_dist_dballeincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_dist_dballeinclude_HEADERS)'; test -n "$(dballeincludedir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(dballeincludedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-local check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(dballeincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f benchmark/$(DEPDIR)/$(am__dirstamp) -rm -f benchmark/$(am__dirstamp) -rm -f cmdline/$(DEPDIR)/$(am__dirstamp) -rm -f cmdline/$(am__dirstamp) -rm -f core/$(DEPDIR)/$(am__dirstamp) -rm -f core/$(am__dirstamp) -rm -f db/$(DEPDIR)/$(am__dirstamp) -rm -f db/$(am__dirstamp) -rm -f db/mem/$(DEPDIR)/$(am__dirstamp) -rm -f db/mem/$(am__dirstamp) -rm -f db/mysql/$(DEPDIR)/$(am__dirstamp) -rm -f db/mysql/$(am__dirstamp) -rm -f db/odbc/$(DEPDIR)/$(am__dirstamp) -rm -f db/odbc/$(am__dirstamp) -rm -f db/postgresql/$(DEPDIR)/$(am__dirstamp) -rm -f db/postgresql/$(am__dirstamp) -rm -f db/sql/$(DEPDIR)/$(am__dirstamp) -rm -f db/sql/$(am__dirstamp) -rm -f db/sqlite/$(DEPDIR)/$(am__dirstamp) -rm -f db/sqlite/$(am__dirstamp) -rm -f db/v6/$(DEPDIR)/$(am__dirstamp) -rm -f db/v6/$(am__dirstamp) -rm -f memdb/$(DEPDIR)/$(am__dirstamp) -rm -f memdb/$(am__dirstamp) -rm -f msg/$(DEPDIR)/$(am__dirstamp) -rm -f msg/$(am__dirstamp) -rm -f msg/aof_importers/$(DEPDIR)/$(am__dirstamp) -rm -f msg/aof_importers/$(am__dirstamp) -rm -f msg/wr_exporters/$(DEPDIR)/$(am__dirstamp) -rm -f msg/wr_exporters/$(am__dirstamp) -rm -f msg/wr_importers/$(DEPDIR)/$(am__dirstamp) -rm -f msg/wr_importers/$(am__dirstamp) -rm -f simple/$(DEPDIR)/$(am__dirstamp) -rm -f simple/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) benchmark/$(DEPDIR) cmdline/$(DEPDIR) core/$(DEPDIR) db/$(DEPDIR) db/mem/$(DEPDIR) db/mysql/$(DEPDIR) db/odbc/$(DEPDIR) db/postgresql/$(DEPDIR) db/sql/$(DEPDIR) db/sqlite/$(DEPDIR) db/v6/$(DEPDIR) memdb/$(DEPDIR) msg/$(DEPDIR) msg/aof_importers/$(DEPDIR) msg/wr_exporters/$(DEPDIR) msg/wr_importers/$(DEPDIR) simple/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-nobase_dist_dballeincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) benchmark/$(DEPDIR) cmdline/$(DEPDIR) core/$(DEPDIR) db/$(DEPDIR) db/mem/$(DEPDIR) db/mysql/$(DEPDIR) db/odbc/$(DEPDIR) db/postgresql/$(DEPDIR) db/sql/$(DEPDIR) db/sqlite/$(DEPDIR) db/v6/$(DEPDIR) memdb/$(DEPDIR) msg/$(DEPDIR) msg/aof_importers/$(DEPDIR) msg/wr_exporters/$(DEPDIR) msg/wr_importers/$(DEPDIR) simple/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES \ uninstall-nobase_dist_dballeincludeHEADERS .MAKE: all check check-am install 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 clean-noinstPROGRAMS 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_dballeincludeHEADERS install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \ uninstall-nobase_dist_dballeincludeHEADERS .PRECIOUS: Makefile # # Autobuilt files # core/record_keyword.cc: core/record_keyword.gperf if ! gperf < $< > $@; then rm $@; /bin/false; fi core/aliases.cc: core/aliases.gperf if ! gperf < $< > $@; then rm $@; /bin/false; fi core/aliases-reverse.cc: core/aliases.gperf core/mkaliasdoc $(srcdir)/core/mkaliasdoc revsolver < $< > $@ msg/vars.h msg/vars.gperf msg/msg-extravars.h msg/context-extravars.h: msg/vars.csv msg/mkvars $(srcdir)/msg/mkvars msg < $< msg/vars.cc: msg/vars.gperf if ! gperf < $< > $@; then rm $@; /bin/false; fi #TESTS = $(check_PROGRAMS) check-local: for test in $(check_PROGRAMS); do \ $(TESTS_ENVIRONMENT) $$test ; \ done core/record_keyword.rst: core/record_keyword.gperf core/mkkeydoc dump-core-info ./dump-core-info keywords | $(srcdir)/core/mkkeydoc rst > $@ core/record_keyword.dox: core/record_keyword.gperf core/mkkeydoc dump-core-info ./dump-core-info keywords | $(srcdir)/core/mkkeydoc dox > $@ core/record_keyword.tex: core/record_keyword.gperf core/mkkeydoc dump-core-info ./dump-core-info keywords | $(srcdir)/core/mkkeydoc tex > $@ core/aliases.dox: core/aliases.gperf core/mkaliasdoc $(srcdir)/core/mkaliasdoc dox < $< > $@ core/aliases.tex: core/aliases.gperf core/mkaliasdoc $(srcdir)/core/mkaliasdoc tex < $< > $@ msg/ltypes.dox: msg/ltypes.txt msg/mklevels $(srcdir)/msg/mklevels dox < $< > $@ msg/ltypes.tex: msg/ltypes.txt msg/mklevels $(srcdir)/msg/mklevels tex < $< > $@ msg/tranges.dox: msg/mktranges $(srcdir)/msg/mktranges dox < $< > $@ msg/tranges.tex: msg/mktranges $(srcdir)/msg/mktranges tex < $< > $@ # 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: dballe-7.7/dballe/var-test.cc0000644000175000017500000000166412652630043013042 00000000000000#include "core/tests.h" #include "var.h" using namespace std; using namespace wreport::tests; using namespace dballe; using namespace wreport; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("resolve", []() { wassert(actual(resolve_varcode("B12101")) == WR_VAR(0, 12, 101)); wassert(actual(resolve_varcode("t")) == WR_VAR(0, 12, 101)); try { resolve_varcode("B121"); throw TestFailed("an exception should be thrown"); } catch (TestFailed) { throw; } catch (std::exception& e) { wassert(actual(e.what()).contains("cannot parse")); } }); add_method("varinfo", []() { Varinfo i = varinfo(WR_VAR(0, 12, 101)); wassert(actual(i->unit) == "K"); }); } } test("dballe_var"); } dballe-7.7/dballe/record.cc0000644000175000017500000000252712652630043012552 00000000000000#include "record.h" #include "core/record.h" #include "var.h" using namespace wreport; using namespace std; namespace dballe { std::unique_ptr Record::create() { return unique_ptr(new core::Record); } const Var& Record::operator[](const char* key) const { const Var* res = get(key); if (!res) error_notfound::throwf("key '%s' not found in record", key); if (!res->isset()) error_notfound::throwf("key '%s' is unset in record", key); return *res; } bool Record::operator==(const Record& rec) const { return equals(rec); } bool Record::operator!=(const Record& rec) const { return !equals(rec); } bool Record::isset(const char* key) const { const Var* res = get(key); if (!res) return false; if (!res->isset()) return false; return true; } wreport::Varinfo Record::key_info(const char* key) { using namespace dballe::core; dba_keyword k = core::Record::keyword_byname(key); if (k != DBA_KEY_ERROR) return core::Record::keyword_info(k); return varinfo(resolve_varcode(key)); } wreport::Varinfo Record::key_info(const std::string& key) { using namespace dballe::core; dba_keyword k = core::Record::keyword_byname_len(key.data(), key.size()); if (k != DBA_KEY_ERROR) return core::Record::keyword_info(k); return varinfo(resolve_varcode(key)); } } dballe-7.7/dballe/record-test.cc0000644000175000017500000000243612652630043013526 00000000000000#include "core/tests.h" #include "record.h" #include using namespace std; using namespace wreport::tests; using namespace dballe; using namespace wreport; namespace { ostream& operator<<(ostream& out, Vartype t) { return out << vartype_format(t); } class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("record", []() { }); add_method("foreach_key", []() { auto rec = Record::create(); rec->set("lat", 44.5); rec->set("B12101", 290.4); vector res; rec->foreach_key([&](const char* key, std::unique_ptr&& var) { res.push_back(string(key) + "=" + var->format()); }); sort(res.begin(), res.end()); wassert(actual(res.size()) == 2); wassert(actual(res[0]) == "B12101=290.40"); wassert(actual(res[1]) == "lat=44.50000"); }); add_method("metadata", []() { wreport::Varinfo info = Record::key_info("rep_memo"); wassert(actual(info->type) == Vartype::String); info = Record::key_info("ana_id"); wassert(actual(info->type) == Vartype::Integer); }); } } test("dballe_record"); } dballe-7.7/dballe/var.h0000644000175000017500000000347512652630043011731 00000000000000#ifndef DBALLE_VAR_H #define DBALLE_VAR_H /** * @file * * Create wreport variables from the DB-All.e B table */ #include #include #include namespace dballe { /// Return a Varinfo entry from the DB-All.e B table wreport::Varinfo varinfo(wreport::Varcode code); /// Return a Varinfo entry from the DB-All.e B table wreport::Varinfo varinfo(const char* code); /// Return a Varinfo entry from the DB-All.e B table wreport::Varinfo varinfo(const std::string& code); /** * Resolve a variable name to a varcode proper, dealing with aliases and * validation */ wreport::Varcode resolve_varcode(const char* name); /** * Resolve a variable name to a varcode proper, dealing with aliases and * validation */ wreport::Varcode resolve_varcode(const std::string& name); /// Create a new Var, from the DB-All.e B table, with undefined value template static inline wreport::Var var(C code) { return wreport::Var(varinfo(code)); } /// Create a new Var, from the DB-All.e B table, with value template static inline wreport::Var var(C code, const T& val) { return wreport::Var(varinfo(code), val); } /// Create a new Var, as a copy of an existing variable static inline std::unique_ptr newvar(const wreport::Var& var) { return std::unique_ptr(new wreport::Var(var)); } /// Create a new Var, from the DB-All.e B table, with undefined value template static inline std::unique_ptr newvar(C code) { return std::unique_ptr(new wreport::Var(varinfo(code))); } /// Create a new Var, from the DB-All.e B table, with value template std::unique_ptr newvar(C code, const T& val) { return std::unique_ptr(new wreport::Var(varinfo(code), val)); } } #endif dballe-7.7/dballe/db/0000755000175000017500000000000012653425050011425 500000000000000dballe-7.7/dballe/db/summary-test.cc0000644000175000017500000001167112652630043014333 00000000000000#include "db/tests.h" #include "summary.h" #include "config.h" using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("summary", [](Fixture& f) { // Test building a summary and checking if it supports queries wassert(f.populate()); core::Query query; query.query = "details"; Summary s(query); wassert(actual(s.is_valid()).isfalse()); // Build the whole db summary auto cur = f.db->query_summary(query); while (cur->next()) s.add_summary(*cur, true); // Check its contents wassert(actual(s.is_valid()).istrue()); if (f.db->format() == V6) wassert(actual(s.all_stations.size()) == 1); else wassert(actual(s.all_stations.size()) == 2); wassert(actual(s.all_levels.size()) == 1); wassert(actual(s.all_tranges.size()) == 2); wassert(actual(s.all_varcodes.size()) == 2); wassert(actual(s.datetime_min()) == Datetime(1945, 4, 25, 8)); wassert(actual(s.datetime_max()) == Datetime(1945, 4, 25, 8, 30)); wassert(actual(s.data_count()) == 4); // Check what it can support // An existing station is ok: we know we have it wassert(actual(s.supports(*query_from_string("ana_id=1"))) == summary::Support::EXACT); // A non-existing station is also ok: we know we don't have it wassert(actual(s.supports(*query_from_string("ana_id=2"))) == summary::Support::EXACT); wassert(actual(s.supports(*query_from_string("ana_id=1, leveltype1=10"))) == summary::Support::EXACT); wassert(actual(s.supports(*query_from_string("ana_id=1, leveltype1=10, pindicator=20"))) == summary::Support::EXACT); wassert(actual(s.supports(*query_from_string("ana_id=1, leveltype1=10, pindicator=20"))) == summary::Support::EXACT); // Still exact, because the query matches the entire summary wassert(actual(s.supports(*query_from_string("yearmin=1945"))) == summary::Support::EXACT); // Still exact, because although the query partially matches the summary, // each summary entry is entier included completely or excluded completely wassert(actual(s.supports(*query_from_string("yearmin=1945, monthmin=4, daymin=25, hourmin=8, yearmax=1945, monthmax=4, daymax=25, hourmax=8, minumax=10"))) == summary::Support::EXACT); }); add_method("summary_stack", [](Fixture& f) { // Test summary::Stack using namespace summary; wassert(f.populate()); core::Query query; query.query = "details"; Summary s(query); wassert(actual(s.is_valid()).isfalse()); Stack stack; // Build the whole db summary Summary& general = stack.push(core::Query()); auto cur = f.db->query_summary(query); while (cur->next()) general.add_summary(*cur, true); wassert(actual(stack.size()) == 1); wassert(actual(stack.top().data_count()) == 4); // Query the stack query.clear(); query.rep_memo = "synop"; Support res = stack.query(query, true, [](const Entry& e) { return e.rep_memo == "synop"; }); wassert(actual(res) == EXACT); wassert(actual(stack.size()) == 2); wassert(actual(stack.top().data_count()) == 2); // Query further query.clear(); query.rep_memo = "synop"; query.varcodes.insert(WR_VAR(0, 1, 11)); res = stack.query(query, true, [](const Entry& e) { return e.rep_memo == "synop" && e.varcode == WR_VAR(0, 1, 11); }); wassert(actual(res) == EXACT); wassert(actual(stack.size()) == 2); wassert(actual(stack.top().data_count()) == 1); // Query the same var but a different rep_memo query.clear(); query.rep_memo = "metar"; query.varcodes.insert(WR_VAR(0, 1, 11)); res = stack.query(query, true, [](const Entry& e) { return e.rep_memo == "metar" && e.varcode == WR_VAR(0, 1, 11); }); wassert(actual(res) == EXACT); wassert(actual(stack.size()) == 2); wassert(actual(stack.top().data_count()) == 1); }); } }; Tests tg1("db_summary_mem", nullptr, db::MEM); Tests tg2("db_summary_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg4("db_summary_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg6("db_summary_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg8("db_summary_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/defs.h0000644000175000017500000000301612652630043012436 00000000000000/* * dballe/db/defs - Base definitions for dballe DB implementations * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_DEFS_H #define DBALLE_DB_DEFS_H #include /** * Flags controlling message import * @{ */ /* Import the attributes. */ #define DBA_IMPORT_ATTRS 1 /* Attempt to merge pseudoana extra information into the existing ones. */ #define DBA_IMPORT_FULL_PSEUDOANA 2 /* Message data will overwrite existing values; otherwise, trying to insert * existing data will cause an error. */ #define DBA_IMPORT_OVERWRITE 8 /// @} namespace dballe { namespace db { /** * Supported formats */ typedef enum { V5 = 0, V6 = 1, MEM = 2, MESSAGES = 3, } Format; /// Base exception for database errors struct error : public wreport::error {}; } } #endif dballe-7.7/dballe/db/querybuf-test.cc0000644000175000017500000000262512652630043014477 00000000000000#include "db/tests.h" #include "db/querybuf.h" using namespace wreport; using namespace dballe; using namespace dballe::tests; using namespace std; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("append", []() { Querybuf buf(10); // A new querybuf contains the empty string wassert(actual(buf) == string()); // Clearing should still be empty buf.clear(); wassert(actual(buf) == string()); buf.append("ciao"); wassert(actual(buf) == "ciao"); wassert(actual(buf.size()) == 4); buf.appendf("%d %s", 42, "--"); wassert(actual(buf) == "ciao42 --"); wassert(actual(buf.size()) == 9); buf.clear(); wassert(actual(buf) == string()); buf.append("123456789"); wassert(actual(buf) == "123456789"); buf.clear(); buf.start_list(", "); buf.append_list("1"); buf.append_list("2"); buf.append_listf("%d", 3); wassert(actual(buf) == "1, 2, 3"); }); add_method("varlist", []() { Querybuf buf(50); buf.append_varlist("B12101,B12103,block"); wassert(actual((string)buf) == "3173,3175,257"); }); } } test("db_querybuf"); } dballe-7.7/dballe/db/db-query-data-test.cc0000644000175000017500000004474312652630043015303 00000000000000#include "db/tests.h" #include "config.h" using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { static inline core::Query query_exact(const Datetime& dt) { core::Query query; query.datetime = DatetimeRange(dt, dt); return query; } static inline core::Query query_min(const Datetime& dt) { core::Query query; query.datetime = DatetimeRange(dt, Datetime()); return query; } static inline core::Query query_max(const Datetime& dt) { core::Query query; query.datetime = DatetimeRange(Datetime(), dt); return query; } static inline core::Query query_minmax(const Datetime& min, const Datetime& max) { core::Query query; query.datetime = DatetimeRange(min, max); return query; } struct DateHourDataSet : public TestDataSet { DateHourDataSet() { DataValues d; d.info.coords = Coords(12.34560, 76.54320); d.info.report = "synop"; d.info.level = Level(10, 11, 15, 22); d.info.trange = Trange(20, 111, 122); data["1"] = d; data["1"].info.datetime = Datetime(2013, 10, 30, 11); data["1"].values.set("B12101", 11.5); data["2"] = d; data["2"].info.datetime = Datetime(2013, 10, 30, 12); data["2"].values.set("B12101", 12.5); } }; struct DateDayDataSet : public TestDataSet { DateDayDataSet() { DataValues d; d.info.coords = Coords(12.34560, 76.54320); d.info.report = "synop"; d.info.level = Level(10, 11, 15, 22); d.info.trange = Trange(20, 111, 122); data["1"] = d; data["1"].info.datetime = Datetime(2013, 10, 23); data["1"].values.set("B12101", 23.5); data["2"] = d; data["2"].info.datetime = Datetime(2013, 10, 24); data["2"].values.set("B12101", 24.5); } }; #define TRY_QUERY(qstring, expected_count) wassert(actual(*f.db).try_data_query(qstring, expected_count)) class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("ana_id", [](Fixture& f) { OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); char query[20]; snprintf(query, 20, "ana_id=%d", oldf.data["synop"].info.ana_id); #warning FIXME: change after testing if we can move to report-in-station behaviour or not if (f.db->format() == MEM) TRY_QUERY(query, 2); else TRY_QUERY(query, 4); TRY_QUERY("ana_id=4242", 0); }); add_method("ana_context", [](Fixture& f) { wassert(f.populate()); // Query data in station context core::Query query; unique_ptr cur = f.db->query_station_data(query); wassert(actual(cur->remaining()) == 10); }); add_method("year", [](Fixture& f) { wassert(f.populate()); // Datetime queries TRY_QUERY("year=1001", 0); TRY_QUERY("yearmin=1999", 0); TRY_QUERY("yearmin=1945", 4); TRY_QUERY("yearmax=1944", 0); TRY_QUERY("yearmax=1945", 4); TRY_QUERY("yearmax=2030", 4); TRY_QUERY("year=1944", 0); TRY_QUERY("year=1945", 4); TRY_QUERY("year=1946", 0); /* TRY_QUERY(i, DBA_KEY_MONTHMIN, 1); TRY_QUERY(i, DBA_KEY_MONTHMAX, 12); TRY_QUERY(i, DBA_KEY_MONTH, 5); */ /* TRY_QUERY(i, DBA_KEY_DAYMIN, 1); TRY_QUERY(i, DBA_KEY_DAYMAX, 12); TRY_QUERY(i, DBA_KEY_DAY, 5); */ /* TRY_QUERY(i, DBA_KEY_HOURMIN, 1); TRY_QUERY(i, DBA_KEY_HOURMAX, 12); TRY_QUERY(i, DBA_KEY_HOUR, 5); */ /* TRY_QUERY(i, DBA_KEY_MINUMIN, 1); TRY_QUERY(i, DBA_KEY_MINUMAX, 12); TRY_QUERY(i, DBA_KEY_MIN, 5); */ /* TRY_QUERY(i, DBA_KEY_SECMIN, 1); TRY_QUERY(i, DBA_KEY_SECMAX, 12); TRY_QUERY(i, DBA_KEY_SEC, 5); */ }); add_method("block_station", [](Fixture& f) { wassert(f.populate()); #warning FIXME: change after testing if we can move to report-in-station behaviour or not const int all = (f.db->format() == MEM ? 4 : 4); // Block and station queries TRY_QUERY("B01001=1", all); TRY_QUERY("B01001=2", 0); TRY_QUERY("B01002=52", all); TRY_QUERY("B01002=53", 0); }); add_method("ana_filter", [](Fixture& f) { #warning FIXME: change after testing if we can move to report-in-station behaviour or not const int all = (f.db->format() == MEM ? 4 : 4); wassert(f.populate()); // ana_filter queries TRY_QUERY("ana_filter=block=1", all); TRY_QUERY("ana_filter=B01001=1", all); TRY_QUERY("ana_filter=block>1", 0); TRY_QUERY("ana_filter=B01001>1", 0); TRY_QUERY("ana_filter=block<=1", all); TRY_QUERY("ana_filter=B01001<=1", all); TRY_QUERY("ana_filter=0<=B01001<=2", all); TRY_QUERY("ana_filter=1<=B01001<=1", all); TRY_QUERY("ana_filter=2<=B01001<=4", 0); }); add_method("data_filter", [](Fixture& f) { wassert(f.populate()); // data_filter queries TRY_QUERY("data_filter=B01011=DB-All.e!", 1); TRY_QUERY("data_filter=B01012<300", 0); TRY_QUERY("data_filter=B01012<=300", 1); TRY_QUERY("data_filter=B01012=300", 1); TRY_QUERY("data_filter=B01012>=300", 2); TRY_QUERY("data_filter=B01012>300", 1); TRY_QUERY("data_filter=B01012<400", 1); TRY_QUERY("data_filter=B01012<=400", 2); }); add_method("latlon", [](Fixture& f) { wassert(f.populate()); // latitude/longitude queries TRY_QUERY("latmin=11.0", 4); TRY_QUERY("latmin=12.34560", 4); TRY_QUERY("latmin=13.0", 0); TRY_QUERY("latmax=11.0", 0); TRY_QUERY("latmax=12.34560", 4); TRY_QUERY("latmax=13.0", 4); TRY_QUERY("latmin=0, latmax=20", 4); TRY_QUERY("latmin=-90, latmax=20", 4); TRY_QUERY("latmin=-90, latmax=0", 0); TRY_QUERY("latmin=10, latmax=90", 4); TRY_QUERY("latmin=45, latmax=90", 0); TRY_QUERY("latmin=-90, latmax=90", 4); TRY_QUERY("lonmin=75, lonmax=77", 4); TRY_QUERY("lonmin=76.54320, lonmax=76.54320", 4); TRY_QUERY("lonmin=76.54330, lonmax=77.", 0); TRY_QUERY("lonmin=77., lonmax=76.54330", 4); TRY_QUERY("lonmin=77., lonmax=76.54320", 4); TRY_QUERY("lonmin=77., lonmax=-10", 0); TRY_QUERY("lonmin=0., lonmax=360.", 4); TRY_QUERY("lonmin=-180., lonmax=180.", 4); }); add_method("mobile", [](Fixture& f) { wassert(f.populate()); // fixed/mobile queries TRY_QUERY("mobile=0", 4); TRY_QUERY("mobile=1", 0); }); // ident queries // FIXME: we currently have no mobile station data in the samples //TRY_QUERY(c, DBA_KEY_IDENT_SELECT, "pippo"); add_method("timerange", [](Fixture& f) { wassert(f.populate()); // timerange queries TRY_QUERY("pindicator=20", 4); TRY_QUERY("pindicator=21", 0); TRY_QUERY("p1=111", 4); TRY_QUERY("p1=112", 0); TRY_QUERY("p2=121", 0); TRY_QUERY("p2=122", 2); TRY_QUERY("p2=123", 2); }); add_method("level", [](Fixture& f) { wassert(f.populate()); // level queries TRY_QUERY("leveltype1=10", 4); TRY_QUERY("leveltype1=11", 0); TRY_QUERY("leveltype2=15", 4); TRY_QUERY("leveltype2=16", 0); TRY_QUERY("l1=11", 4); TRY_QUERY("l1=12", 0); TRY_QUERY("l2=22", 4); TRY_QUERY("l2=23", 0); }); add_method("varcode", [](Fixture& f) { wassert(f.populate()); // varcode queries TRY_QUERY("var=B01011", 2); TRY_QUERY("var=B01012", 2); TRY_QUERY("var=B01013", 0); }); add_method("report", [](Fixture& f) { wassert(f.populate()); // report queries TRY_QUERY("rep_memo=synop", 2); TRY_QUERY("rep_memo=metar", 2); TRY_QUERY("rep_memo=temp", 0); }); add_method("priority", [](Fixture& f) { wassert(f.populate()); // report priority queries TRY_QUERY("priority=101", 2); TRY_QUERY("priority=81", 2); TRY_QUERY("priority=102", 0); TRY_QUERY("priomin=70", 4); TRY_QUERY("priomin=80", 4); TRY_QUERY("priomin=90", 2); TRY_QUERY("priomin=100", 2); TRY_QUERY("priomin=110", 0); TRY_QUERY("priomax=70", 0); TRY_QUERY("priomax=81", 2); TRY_QUERY("priomax=100", 2); TRY_QUERY("priomax=101", 4); TRY_QUERY("priomax=110", 4); }); add_method("datetime1", [](Fixture& f) { // Check datetime queries, with data that only differs by its hour wassert(f.populate()); auto& db = *f.db; // Valid hours: 11 and 12 // Exact match wassert(actual(db).try_data_query(query_exact(Datetime(2013, 10, 30, 10)), 0)); wassert(actual(db).try_data_query(query_exact(Datetime(2013, 10, 30, 11)), 1)); wassert(actual(db).try_data_query(query_exact(Datetime(2013, 10, 30, 12)), 1)); wassert(actual(db).try_data_query(query_exact(Datetime(2013, 10, 30, 13)), 0)); // Datemin match wassert(actual(db).try_data_query(query_min(Datetime(2013, 10, 30, 10)), 2)); wassert(actual(db).try_data_query(query_min(Datetime(2013, 10, 30, 11)), 2)); wassert(actual(db).try_data_query(query_min(Datetime(2013, 10, 30, 12)), 1)); wassert(actual(db).try_data_query(query_min(Datetime(2013, 10, 30, 13)), 0)); // Datemax match wassert(actual(db).try_data_query(query_max(Datetime(2013, 10, 30, 13)), 2)); wassert(actual(db).try_data_query(query_max(Datetime(2013, 10, 30, 12)), 2)); wassert(actual(db).try_data_query(query_max(Datetime(2013, 10, 30, 11)), 1)); wassert(actual(db).try_data_query(query_max(Datetime(2013, 10, 30, 10)), 0)); // Date min-max match wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 30, 10), Datetime(2013, 10, 30, 13)), 2)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 30, 11), Datetime(2013, 10, 30, 12)), 2)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 30, 10), Datetime(2013, 10, 30, 11)), 1)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 30, 12), Datetime(2013, 10, 30, 13)), 1)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 30, 9), Datetime(2013, 10, 30, 10)), 0)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 30, 13), Datetime(2013, 10, 30, 14)), 0)); }); add_method("datetime2", [](Fixture& f) { // Check datetime queries, with data that only differs by its day wassert(f.populate()); auto& db = *f.db; // Valid days: 23 and 24 // Exact match wassert(actual(db).try_data_query(query_exact(Datetime(2013, 10, 22)), 0)); wassert(actual(db).try_data_query(query_exact(Datetime(2013, 10, 23)), 1)); wassert(actual(db).try_data_query(query_exact(Datetime(2013, 10, 24)), 1)); wassert(actual(db).try_data_query(query_exact(Datetime(2013, 10, 25)), 0)); // Datemin match wassert(actual(db).try_data_query(query_min(Datetime(2013, 10, 22)), 2)); wassert(actual(db).try_data_query(query_min(Datetime(2013, 10, 23)), 2)); wassert(actual(db).try_data_query(query_min(Datetime(2013, 10, 24)), 1)); wassert(actual(db).try_data_query(query_min(Datetime(2013, 10, 25)), 0)); // Datemax match wassert(actual(db).try_data_query(query_max(Datetime(2013, 10, 25)), 2)); wassert(actual(db).try_data_query(query_max(Datetime(2013, 10, 24)), 2)); wassert(actual(db).try_data_query(query_max(Datetime(2013, 10, 23)), 1)); wassert(actual(db).try_data_query(query_max(Datetime(2013, 10, 22)), 0)); // Date min-max match wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 22), Datetime(2013, 10, 25)), 2)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 23), Datetime(2013, 10, 24)), 2)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 23), Datetime(2013, 10, 23)), 1)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 24), Datetime(2013, 10, 24)), 1)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 22), Datetime(2013, 10, 23)), 1)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 24), Datetime(2013, 10, 25)), 1)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 21), Datetime(2013, 10, 22)), 0)); wassert(actual(db).try_data_query(query_minmax(Datetime(2013, 10, 25), Datetime(2013, 10, 26)), 0)); }); add_method("query_ordering", [](Fixture& f) { auto& db = *f.db; auto insert = [&](const char* str) { core::Record rec; rec.set_from_test_string(str); DataValues vals(rec); db.insert_data(vals, false, true); return vals; }; auto vals01 = insert("lat=1, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=a, B12101=280.15"); auto vals02 = insert("lat=2, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=a, B12101=280.15"); auto vals03 = insert("lat=1, lon=1, year=2001, leveltype1=1, pindicator=1, rep_memo=a, B12101=280.15"); auto vals04 = insert("lat=1, lon=1, year=2000, leveltype1=2, pindicator=1, rep_memo=a, B12101=280.15"); auto vals05 = insert("lat=1, lon=1, year=2000, leveltype1=1, pindicator=2, rep_memo=a, B12101=280.15"); auto vals06 = insert("lat=1, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=b, B12101=280.15"); auto vals07 = insert("lat=1, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=a, B12103=280.15"); auto cur = db.query_data(core::Query()); wassert(actual(cur->remaining()) == 7); core::Record test; switch (db.format()) { case MEM: // mem: coords, ident, datetime, level, trange, code, report wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals01)); // lat=1, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=a, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals07)); // lat=1, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=a, B12103=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals06)); // lat=1, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=b, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals05)); // lat=1, lon=1, year=2000, leveltype1=1, pindicator=2, rep_memo=a, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals04)); // lat=1, lon=1, year=2000, leveltype1=2, pindicator=1, rep_memo=a, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals03)); // lat=1, lon=1, year=2001, leveltype1=1, pindicator=1, rep_memo=a, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals02)); // lat=2, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=a, B12101=280.15 break; case V6: // V6: ana_id, datetime, level, trange, report, var wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals01)); // lat=1, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=a, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals07)); // lat=1, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=a, B12103=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals06)); // lat=1, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=b, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals05)); // lat=1, lon=1, year=2000, leveltype1=1, pindicator=2, rep_memo=a, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals04)); // lat=1, lon=1, year=2000, leveltype1=2, pindicator=1, rep_memo=a, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals03)); // lat=1, lon=1, year=2001, leveltype1=1, pindicator=1, rep_memo=a, B12101=280.15 wassert(actual(cur->next())); wassert(actual(cur).data_matches(vals02)); // lat=2, lon=1, year=2000, leveltype1=1, pindicator=1, rep_memo=a, B12101=280.15 // cur->to_record(test); test.print(stderr); break; default: error_unimplemented::throwf("cannot run this test on a database of format %d", (int)db.format()); } }); } }; Tests tg1("db_query_data_mem", nullptr, db::MEM); Tests tg2("db_query_data_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg4("db_query_data_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg6("db_query_data_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg8("db_query_data_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/trace-test.cc0000644000175000017500000001454012652630043013732 00000000000000#include "db/tests.h" using namespace std; using namespace dballe; using namespace dballe::tests; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { #if 0 // Test simple queries Test("reset", [](Fixture& f) { // Run twice to see if it is idempotent auto& db = *f.db; db.reset(); db.reset(); }), Test("repinfo", [](Fixture& f) { // Test repinfo-related functions auto& db = *f.db; std::map prios = db.get_repinfo_priorities(); wassert(actual(prios.find("synop") != prios.end()).istrue()); wassert(actual(prios["synop"]) == 101); int added, deleted, updated; db.update_repinfo((string(getenv("DBA_TESTDATA")) + "/test-repinfo1.csv").c_str(), &added, &deleted, &updated); wassert(actual(added) == 3); wassert(actual(deleted) == 11); wassert(actual(updated) == 2); prios = db.get_repinfo_priorities(); wassert(actual(prios.find("fixspnpo") != prios.end()).istrue()); wassert(actual(prios["fixspnpo"]) == 200); }), Test("vacuum", [](Fixture& f) { // Just invoke vacuum auto& db = *f.db; db.vacuum(); }), Test("simple", [](Fixture& f) { // Test remove_all auto& db = *f.db; db.remove_all(); Query query; std::unique_ptr cur = db.query_data(query); wassert(actual(cur->remaining()) == 0); // Check that it is idempotent db.remove_all(); cur = db.query_data(query); wassert(actual(cur->remaining()) == 0); // Insert something wruntest(f.populate); cur = db.query_data(query); wassert(actual(cur->remaining()) == 4); db.remove_all(); cur = db.query_data(query); wassert(actual(cur->remaining()) == 0); }), Test("stationdata", [](Fixture& f) { // Test adding station data for different networks auto& db = *f.db; db.reset(); Record rec; rec.set(DBA_KEY_LAT, 12.077); rec.set(DBA_KEY_LON, 44.600); // Insert two values in two networks rec.set(Level(103, 2000)); rec.set(Trange::instant()); rec.set(Datetime(2014, 1, 1, 0, 0, 0)); rec.set(DBA_KEY_REP_MEMO, "synop"); rec.set(WR_VAR(0, 12, 101), 273.15); db.insert(rec, true, true); rec.set(DBA_KEY_REP_MEMO, "temp"); rec.set(WR_VAR(0, 12, 101), 274.15); db.insert(rec, true, true); // Insert station names in both networks rec.set_ana_context(); rec.set(DBA_KEY_REP_MEMO, "synop"); rec.set(WR_VAR(0, 1, 19), "Camse"); db.insert(rec, true, true); rec.set(DBA_KEY_REP_MEMO, "temp"); rec.set(WR_VAR(0, 1, 19), "Esmac"); db.insert(rec, true, true); // Query back all the data Query query; auto cur = db.query_stations(query); // Check results Record result; if (dynamic_cast(f.db)) { // For mem databases, we get one record per (station, network) // combination wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_station_id()) == 1); wassert(actual(cur->get_rep_memo()) == "temp"); cur->to_record(result); wassert(actual(result.get(WR_VAR(0, 1, 19)).value()) == "Esmac"); wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_station_id()) == 0); wassert(actual(cur->get_rep_memo()) == "synop"); cur->to_record(result); wassert(actual(result.get(WR_VAR(0, 1, 19)).value()) == "Camse"); } else { // For normal databases, we only get one record, with the station // values merged keeping values for the best networks wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_station_id()) == 1); cur->to_record(result); wassert(actual(result.get(WR_VAR(0, 1, 19)).value()) == "Camse"); wassert(actual(cur->next()).isfalse()); } query.clear(); Msgs msgs; msg::AcquireMessages amsg(msgs); db.export_msgs(query, amsg); wassert(actual(msgs.size()) == 2); //msgs.print(stderr); wassert(actual(msgs[0]->get_rep_memo_var()->enqc()) == "synop"); wassert(actual(msgs[0]->get_st_name_var()->enqc()) == "Camse"); wassert(actual(msgs[0]->get_temp_2m_var()->enqd()) == 273.15); wassert(actual(msgs[1]->get_rep_memo_var()->enqc()) == "temp"); wassert(actual(msgs[1]->get_st_name_var()->enqc()) == "Esmac"); wassert(actual(msgs[1]->get_temp_2m_var()->enqd()) == 274.15); }), Test("query_ident", [](Fixture& f) { // Try querying by ident auto& db = *f.db; // Insert a mobile station Record rec; rec.set_from_string("rep_memo=synop"); rec.set_from_string("lat=44.10"); rec.set_from_string("lon=11.50"); rec.set_from_string("ident=foo"); rec.set(Level(1)); rec.set(Trange::instant()); rec.set(Datetime(2015, 4, 25, 12, 30, 45)); rec.set(WR_VAR(0, 12, 101), 295.1); db.insert(rec, true, true); wassert(actual(db).try_station_query("ident=foo", 1)); wassert(actual(db).try_station_query("ident=bar", 0)); wassert(actual(db).try_station_query("mobile=1", 1)); wassert(actual(db).try_station_query("mobile=0", 0)); wassert(actual(db).try_data_query("ident=foo", 1)); wassert(actual(db).try_data_query("ident=bar", 0)); wassert(actual(db).try_data_query("mobile=1", 1)); wassert(actual(db).try_data_query("mobile=0", 0)); }), #endif } } test("db_trace"); } dballe-7.7/dballe/db/sql/0000755000175000017500000000000012653425050012224 500000000000000dballe-7.7/dballe/db/sql/repinfo.cc0000644000175000017500000002537312652630043014126 00000000000000#include "repinfo.h" #include "dballe/db/sql.h" #include "dballe/db/odbc/internals.h" //#include "dballe/db/odbc/repinfo.h" #include "dballe/db/sqlite/internals.h" //#include "dballe/db/sqlite/repinfo.h" #include "dballe/record.h" #include "dballe/core/query.h" #include "dballe/core/csv.h" #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace sql { Repinfo::Repinfo(Connection& conn) : conn(conn) { } #if 0 std::unique_ptr Repinfo::create(Connection& conn) { if (ODBCConnection* c = dynamic_cast(&conn)) return unique_ptr(new ODBCRepinfo(*c)); else if (SQLiteConnection* c = dynamic_cast(&conn)) return unique_ptr(new SQLiteRepinfo(*c)); else throw error_unimplemented("v5 DB repinfo not yet implemented for non-ODBC connectors"); } #endif void Repinfo::to_record(int id, Record& rec) { const repinfo::Cache* c = get_by_id(id); if (c) { rec.setc("rep_memo", c->memo.c_str()); rec.seti("priority", c->prio); } else { rec.unset("rep_memo"); rec.unset("priority"); } } const char* Repinfo::get_rep_memo(int id) { if (const repinfo::Cache* c = get_by_id(id)) return c->memo.c_str(); error_notfound::throwf("rep_memo not found for report code %d", id); } int Repinfo::get_id(const char* memo) { char lc_memo[20]; int i; for (i = 0; i < 19 && memo[i]; ++i) lc_memo[i] = tolower(memo[i]); lc_memo[i] = 0; if (memo_idx.empty()) rebuild_memo_idx(); int pos = cache_find_by_memo(lc_memo); if (pos == -1) error_notfound::throwf("looking for repinfo corresponding to '%s'", memo); return memo_idx[pos].id; } int Repinfo::get_priority(int id) { const repinfo::Cache* ri_entry = get_by_id(id); return ri_entry ? ri_entry->prio : INT_MAX; } std::map Repinfo::get_priorities() { std::map res; for (std::vector::const_iterator i = cache.begin(); i != cache.end(); ++i) res[i->memo] = i->prio; return res; } int Repinfo::obtain_id(const char* memo) { char lc_memo[20]; int i; for (i = 0; i < 19 && memo[i]; ++i) lc_memo[i] = tolower(memo[i]); lc_memo[i] = 0; if (memo_idx.empty()) rebuild_memo_idx(); int pos = cache_find_by_memo(lc_memo); if (pos == -1) { insert_auto_entry(memo); read_cache(); return get_id(memo); } return memo_idx[pos].id; } std::vector Repinfo::ids_by_prio(const core::Query& q) { vector res; for (std::vector::const_iterator i = cache.begin(); i != cache.end(); ++i) { if (q.prio_min != MISSING_INT && i->prio < q.prio_min) continue; if (q.prio_max != MISSING_INT && i->prio > q.prio_max) continue; res.push_back(i->id); } return res; } const repinfo::Cache* Repinfo::get_by_id(unsigned id) const { int pos = cache_find_by_id(id); return pos == -1 ? NULL : &(cache[pos]); } const repinfo::Cache* Repinfo::get_by_memo(const char* memo) const { int pos = cache_find_by_memo(memo); if (pos == -1) return NULL; return get_by_id(memo_idx[pos].id); } int Repinfo::cache_find_by_id(unsigned id) const { /* Binary search the ID */ int begin, end; begin = -1, end = cache.size(); while (end - begin > 1) { int cur = (end + begin) / 2; if (cache[cur].id > id) end = cur; else begin = cur; } if (begin == -1 || cache[begin].id != id) return -1; else return begin; } int Repinfo::cache_find_by_memo(const char* memo) const { /* Binary search the memo index */ int begin, end; begin = -1, end = cache.size(); while (end - begin > 1) { int cur = (end + begin) / 2; if (memo_idx[cur].memo > memo) end = cur; else begin = cur; } if (begin == -1 || memo_idx[begin].memo != memo) return -1; else return begin; } void Repinfo::cache_append(unsigned id, const char* memo, const char* desc, int prio, const char* descriptor, int tablea) { /* Ensure that we are adding things in order */ if (!cache.empty() && cache.back().id >= id) error_consistency::throwf( "checking that value to append to repinfo cache (%u) " "is greather than the last value in che cache (%u)", id, (unsigned)cache.back().id); memo_idx.clear(); /* Enlarge buffer if needed */ cache.push_back(repinfo::Cache(id, memo, desc, prio, descriptor, tablea)); } void Repinfo::rebuild_memo_idx() const { memo_idx.clear(); memo_idx.resize(cache.size()); for (size_t i = 0; i < cache.size(); ++i) { memo_idx[i].memo = cache[i].memo; memo_idx[i].id = cache[i].id; } std::sort(memo_idx.begin(), memo_idx.end()); } namespace { struct fd_closer { FILE* fd; fd_closer(FILE* fd) : fd(fd) {} ~fd_closer() { fclose(fd); } }; inline void inplace_tolower(std::string& buf) { for (string::iterator i = buf.begin(); i != buf.end(); ++i) *i = tolower(*i); } } std::vector Repinfo::read_repinfo_file(const char* deffile) { if (deffile == 0) deffile = DB::default_repinfo_file(); /* Open the input CSV file */ FILE* in = fopen(deffile, "r"); if (in == NULL) error_system::throwf("opening file %s", deffile); fd_closer closer(in); /* Read the CSV file */ vector newitems; vector columns; for (int line = 1; csv_read_next(in, columns); ++line) { int id, pos; if (columns.size() != 6) error_parse::throwf(deffile, line, "Expected 6 columns, got %zd", columns.size()); // Lowercase all rep_memos inplace_tolower(columns[1]); id = strtol(columns[0].c_str(), 0, 10); pos = cache_find_by_id(id); if (pos == -1) { /* New entry */ newitems.push_back(repinfo::Cache(id, columns[1], columns[2], strtol(columns[3].c_str(), 0, 10), columns[4], strtol(columns[5].c_str(), 0, 10))); newitems.back().make_new(); } else { /* Possible update on an existing entry */ cache[pos].new_memo = columns[1]; cache[pos].new_desc = columns[2]; cache[pos].new_prio = strtol(columns[3].c_str(), 0, 10); cache[pos].new_descriptor = columns[4]; cache[pos].new_tablea = strtol(columns[5].c_str(), 0, 10); } } /* Verify conflicts */ for (size_t i = 0; i < cache.size(); ++i) { /* Skip empty items or items that will be deleted */ if (cache[i].memo.empty() || cache[i].new_memo.empty()) continue; if (cache[i].memo != cache[i].new_memo) error_consistency::throwf("cannot rename rep_cod %d (previous rep_memo was %s, new rep_memo is %s)", (int)cache[i].id, cache[i].memo.c_str(), cache[i].new_memo.c_str()); for (size_t j = i + 1; j < cache.size(); ++j) { /* Skip empty items or items that will be deleted */ if (cache[j].memo.empty() || cache[j].new_memo.empty()) continue; if (cache[j].new_prio == cache[i].new_prio) error_consistency::throwf("%s has the same priority (%d) as %s", cache[j].new_memo.c_str(), (int)cache[j].new_prio, cache[i].new_memo.c_str()); } for (vector::const_iterator j = newitems.begin(); j != newitems.end(); ++j) { if (j->new_prio == cache[i].new_prio) error_consistency::throwf("%s has the same priority (%d) as %s", j->new_memo.c_str(), (int)j->new_prio, cache[i].new_memo.c_str()); } } for (vector::const_iterator i = newitems.begin(); i != newitems.end(); ++i) { /*fprintf(stderr, "prio %d\n", cur->item.new_prio);*/ for (vector::const_iterator j = i + 1; j != newitems.end(); ++j) { if (i->new_prio == j->new_prio) error_consistency::throwf("%s has the same priority (%d) as %s", i->new_memo.c_str(), (int)i->new_prio, j->new_memo.c_str()); } } /* fprintf(stderr, "POST PARSE:\n"); for (const auto& e: cache) e.dump(stderr); */ return newitems; } void Repinfo::update(const char* deffile, int* added, int* deleted, int* updated) { *added = *deleted = *updated = 0; // Read the new repinfo data from file vector newitems = read_repinfo_file(deffile); // Verify that we are not trying to delete a repinfo entry that is // in use for (const auto& entry : cache) /* Ensure that we are not deleting a repinfo entry that is already in use */ if (!entry.memo.empty() && entry.new_memo.empty()) if (id_use_count(entry.id, entry.memo.c_str()) > 0) error_consistency::throwf( "trying to delete repinfo entry %u,%s which is currently in use", (unsigned)entry.id, entry.memo.c_str()); // Perform the changes for (const auto& entry : cache) { if (!entry.memo.empty() && entry.new_memo.empty()) { // Delete the items that were deleted */ delete_entry(entry.id); ++*deleted; } else if (!entry.memo.empty() && !entry.new_memo.empty()) { // Update the items that were modified update_entry(entry); ++*updated; } } // Insert the new items for (const auto& entry : newitems) { insert_entry(entry); ++*added; } // Reread the cache read_cache(); } namespace repinfo { Cache::Cache(int id, const std::string& memo, const std::string& desc, int prio, const std::string& descriptor, int tablea) : id(id), memo(memo), desc(desc), prio(prio), descriptor(descriptor), tablea(tablea), new_prio(0), new_tablea(0) { } void Cache::make_new() { new_memo = memo; new_desc = desc; new_prio = prio; new_descriptor = descriptor; new_tablea = tablea; } void Cache::dump(FILE* out) const { fprintf(stderr, "%u: %s %s %d %s %u (%s %s %d %s %u)\n", id, memo.c_str(), desc.c_str(), prio, descriptor.c_str(), tablea, new_memo.c_str(), new_desc.c_str(), new_prio, new_descriptor.c_str(), new_tablea); } bool Memoidx::operator<(const Memoidx& val) const { return memo < val.memo; } } } } } dballe-7.7/dballe/db/sql/levtr.h0000644000175000017500000000607012652630043013453 00000000000000/* * db/levtr - level-timerange table implementation * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQL_LEVTR_H #define DBALLE_DB_SQL_LEVTR_H #include #include #include namespace dballe { struct Record; struct Msg; namespace msg { struct Context; } namespace db { struct Connection; struct Statement; namespace sql { /** * Precompiled queries to manipulate the lev_tr table */ struct LevTr { struct DBRow { /// lev_tr ID SQL parameter int id; /// First level type SQL parameter int ltype1; /// Level L1 SQL parameter int l1; /// Second level type SQL parameter int ltype2; /// Level L2 SQL parameter int l2; /// Time range type SQL parameter int pind; /// Time range P1 SQL parameter int p1; /// Time range P2 SQL parameter int p2; }; virtual ~LevTr(); /** * Return the ID for the given Level and Trange, adding it to the database * if it does not already exist */ virtual int obtain_id(const Level& lev, const Trange& tr) = 0; /// Read the LevTr data for an id, returns nullptr if not found virtual const DBRow* read(int id) = 0; /// Read the contents of the LevTr table virtual void read_all(std::function dest) = 0; /// Dump the entire contents of the table to an output stream virtual void dump(FILE* out) = 0; }; struct LevTrCache { virtual ~LevTrCache(); /** * Fill a record with level/timerange info with this id. * * @return true if found, else false */ virtual bool to_rec(int id, Record& rec) = 0; /// Return a Level for this ID virtual Level to_level(int id) const = 0; /// Return a Trange for this ID virtual Trange to_trange(int id) const = 0; /** * Get/create a Context in the Msg for this level/timerange. * * @returns the context, or 0 if the id is not valid. */ virtual msg::Context* to_msg(int id, Msg& msg) = 0; /// Invalidate the cache virtual void invalidate() = 0; /// Dump cache contents to an output stream virtual void dump(FILE* out) const = 0; /// Create a new LevTrCache for this LevTr static std::unique_ptr create(LevTr& levtr); }; } } } #endif dballe-7.7/dballe/db/sql/driver.cc0000644000175000017500000001071012652630043013744 00000000000000/* * db/sql/runqueryv6 - db-independent support for specific v6 queries * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "driver.h" #include "config.h" #include "dballe/db/sqlite/driver.h" #include "dballe/db/sqlite/internals.h" #ifdef HAVE_LIBPQ #include "dballe/db/postgresql/driver.h" #include "dballe/db/postgresql/internals.h" #endif #ifdef HAVE_MYSQL #include "dballe/db/mysql/driver.h" #include "dballe/db/mysql/internals.h" #endif #ifdef HAVE_ODBC #include "dballe/db/odbc/driver.h" #include "dballe/db/odbc/internals.h" #endif #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace sql { bool SQLRecordV6::querybest_fields_are_the_same(const SQLRecordV6& r) { if (out_ana_id != r.out_ana_id) return false; if (out_id_ltr != r.out_id_ltr) return false; if (out_datetime != r.out_datetime) return false; if (out_varcode != r.out_varcode) return false; return true; } void SQLRecordV6::dump(FILE* out) { fprintf(out, "st: %d %6d %6d ", out_ana_id, out_lat, out_lon); if (out_ident_size == -1) fputs("fixed, ", out); else fprintf(out, "%.*s, ", out_ident_size, out_ident); fprintf(out, "rc: %d %d, ltr %d, did %d, ", out_rep_cod, priority, out_id_ltr, out_id_data); stringstream s; s << "dt: " << out_datetime << " " << out_datetimemax << ", "; fputs(s.str().c_str(), out); fprintf(out, "%d%02d%03d %s\n", WR_VAR_F(out_varcode), WR_VAR_X(out_varcode), WR_VAR_Y(out_varcode), out_value); } Driver::~Driver() { } void Driver::create_tables(db::Format format) { switch (format) { case V5: throw error_unimplemented("database version V5 is not supported anymore"); case V6: create_tables_v6(); break; default: throw wreport::error_consistency("cannot create tables on the given DB format"); } } void Driver::delete_tables(db::Format format) { switch (format) { case V5: throw error_unimplemented("database version V5 is not supported anymore"); case V6: delete_tables_v6(); break; default: throw wreport::error_consistency("cannot delete tables on the given DB format"); } } void Driver::remove_all(db::Format format) { switch (format) { case V5: throw error_unimplemented("database version V5 is not supported anymore"); case V6: remove_all_v6(); break; default: throw wreport::error_consistency("cannot empty a database with the given format"); } } void Driver::remove_all_v6() { exec_no_data("DELETE FROM attr"); exec_no_data("DELETE FROM data"); exec_no_data("DELETE FROM lev_tr"); exec_no_data("DELETE FROM station"); } void Driver::explain(const std::string& query) { fprintf(stderr, "Explaining query %s is not supported on this db.\n", query.c_str()); } std::unique_ptr Driver::create(Connection& conn) { if (SQLiteConnection* c = dynamic_cast(&conn)) return unique_ptr(new sqlite::Driver(*c)); #ifdef HAVE_ODBC else if (ODBCConnection* c = dynamic_cast(&conn)) return unique_ptr(new odbc::Driver(*c)); #endif #ifdef HAVE_LIBPQ else if (PostgreSQLConnection* c = dynamic_cast(&conn)) return unique_ptr(new postgresql::Driver(*c)); #endif #ifdef HAVE_MYSQL else if (MySQLConnection* c = dynamic_cast(&conn)) return unique_ptr(new mysql::Driver(*c)); #endif else throw error_unimplemented("DB drivers only implemented for " #ifdef HAVE_LIBPQ "PostgreSQL, " #endif #ifdef HAVE_MYSQL "MySQL, " #endif #ifdef HAVE_ODBC "ODBC, " #endif " and SQLite connectors"); } } } } dballe-7.7/dballe/db/sql/station-test.cc0000644000175000017500000000455612652630043015122 00000000000000#include "db/tests.h" #include "db/v6/db.h" #include "db/sql.h" #include "db/sql/station.h" #include "config.h" using namespace dballe; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct Fixture : DriverFixture { using DriverFixture::DriverFixture; unique_ptr station; void reset_station() { if (conn->has_table("station")) driver->exec_no_data("DELETE FROM station"); switch (format) { case db::V5: throw error_unimplemented("v5 db is not supported"); case db::V6: station = driver->create_stationv6(); break; default: throw error_consistency("cannot test station on the current DB format"); } } void test_setup() { DriverFixture::test_setup(); reset_station(); } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("insert", [](Fixture& f) { // Insert some values and try to read them again auto& st = *f.station; bool inserted; // Insert a mobile station wassert(actual(st.obtain_id(4500000, 1100000, "ciao", &inserted)) == 1); wassert(actual(inserted).istrue()); wassert(actual(st.obtain_id(4500000, 1100000, "ciao", &inserted)) == 1); wassert(actual(inserted).isfalse()); // Insert a fixed station wassert(actual(st.obtain_id(4600000, 1200000, NULL, &inserted)) == 2); wassert(actual(inserted).istrue()); wassert(actual(st.obtain_id(4600000, 1200000, NULL, &inserted)) == 2); wassert(actual(inserted).isfalse()); // Get the ID of the first station wassert(actual(st.get_id(4500000, 1100000, "ciao")) == 1); // Get the ID of the second station wassert(actual(st.get_id(4600000, 1200000)) == 2); }); } }; Tests test_sqlite("db_sql_station_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests test_odbc("db_sql_station_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests test_psql("db_sql_station_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests test_mysql("db_sql_station_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/sql/repinfo.h0000644000175000017500000001231112652630043013754 00000000000000#ifndef DBALLE_DB_SQL_REPINFO_H #define DBALLE_DB_SQL_REPINFO_H /** @file * @ingroup db * * Repinfo table management used by the db module. */ #include #include #include #include namespace dballe { struct Record; namespace core { struct Query; } namespace db { struct Connection; namespace sql { namespace repinfo { /** repinfo cache entry */ struct Cache { /// Report code unsigned id; /** Report name */ std::string memo; /** Report description */ std::string desc; /// Report priority int prio; /** Report descriptor (currently unused) */ std::string descriptor; /// Report A table value (currently unused) unsigned tablea; /** New report name used when updating the repinfo table */ std::string new_memo; /** New report description used when updating the repinfo table */ std::string new_desc; /// New report priority used when updating the repinfo table int new_prio; /** New report descriptor used when updating the repinfo table */ std::string new_descriptor; /// New report A table value used when updating the repinfo table unsigned new_tablea; Cache(int id, const std::string& memo, const std::string& desc, int prio, const std::string& descriptor, int tablea); void make_new(); void dump(FILE* out) const; }; /** reverse rep_memo -> rep_cod cache entry */ struct Memoidx { /** Report name */ std::string memo; /** Report code */ int id; bool operator<(const Memoidx& memo) const; }; } /// Fast cached access to the repinfo table struct Repinfo { Connection& conn; Repinfo(Connection& conn); virtual ~Repinfo() {} //static std::unique_ptr create(Connection& conn); /** * Fill repinfo information in a Record based on the repinfo entry with the * given ID */ void to_record(int id, Record& rec); /// Get the rep_memo for a given ID; throws if id is not valud const char* get_rep_memo(int id); /// Get the ID for a given rep_memo; throws if rep_memo is not valid int get_id(const char* rep_memo); /// Get the priority for a given ID; returns INT_MAX if id is not valid int get_priority(int id); /** * Update the report type information in the database using the data from the * given file. * * @param ri * dba_db_repinfo used to update the database * @param deffile * Pathname of the file to use for the update. The NULL value is accepted * and means to use the default configure repinfo.csv file. * @retval added * Number of entries that have been added during the update. * @retval deleted * Number of entries that have been deleted during the update. * @retval updated * Number of entries that have been updated during the update. */ void update(const char* deffile, int* added, int* deleted, int* updated); /** * Get a mapping between rep_memo and their priorities */ std::map get_priorities(); /** * Return a vector of IDs matching the priority constraints in the given record. */ std::vector ids_by_prio(const core::Query& rec); /** * Get the id of a repinfo entry given its name. * * It creates a new entry if the memo is missing from the database. * * @param memo * The name to query * @return * The resulting id. */ int obtain_id(const char* memo); /// Dump the entire contents of the database to an output stream virtual void dump(FILE* out) = 0; protected: /** Cache of table entries */ std::vector cache; /** rep_memo -> rep_cod reverse index */ mutable std::vector memo_idx; /// Get a Cache entry by database ID const repinfo::Cache* get_by_id(unsigned id) const; /// Get a Cache entry by report name const repinfo::Cache* get_by_memo(const char* memo) const; /// Lookup a cache index by database ID. Returns -1 if not found int cache_find_by_id(unsigned id) const; /// Lookup a cache index by report name. Returns -1 if not found int cache_find_by_memo(const char* memo) const; /// Append an entry to the cache void cache_append(unsigned id, const char* memo, const char* desc, int prio, const char* descriptor, int tablea); /// Rebuild the memo_idx cache void rebuild_memo_idx() const; /// Read cache entries from a repinfo file on disk std::vector read_repinfo_file(const char* deffile); /// Return how many time this ID is used in the database virtual int id_use_count(unsigned id, const char* name) = 0; /// Delete a repinfo entry virtual void delete_entry(unsigned id) = 0; /// Update an entry using the new_* fields of \a entry virtual void update_entry(const repinfo::Cache& entry) = 0; /// Insert an entry using the new_* fields of \a entry virtual void insert_entry(const repinfo::Cache& entry) = 0; /// Reread the repinfo cache from the database virtual void read_cache() = 0; /// Create an automatic entry for a missing memo, and insert it in the database virtual void insert_auto_entry(const char* memo) = 0; }; } } } #endif dballe-7.7/dballe/db/sql/levtr.cc0000644000175000017500000000542512652630043013614 00000000000000#include "levtr.h" #include "dballe/core/record.h" #include "dballe/msg/msg.h" #include #include //using namespace wreport; using namespace std; namespace dballe { namespace db { namespace sql { LevTr::~LevTr() {} LevTrCache::~LevTrCache() {} struct MapLevTrCache : public LevTrCache { struct Item { Level level; Trange trange; Item(const LevTr::DBRow& o) : level(o.ltype1, o.l1, o.ltype2, o.l2), trange(o.pind, o.p1, o.p2) {} void to_record(Record& rec) const { rec.set(level); rec.set(trange); } }; mutable LevTr* levtr; mutable map cache; MapLevTrCache(LevTr& levtr) : levtr(&levtr) { // TODO: make prefetch optional if needed, controlled by an env // variable levtr.read_all([&](const LevTr::DBRow& row) { cache.insert(make_pair(row.id, Item(row))); }); } const Item* get(int id) const { map::const_iterator i = cache.find(id); // Cache hit if (i != cache.end()) return &(i->second); // Miss: try the DB const LevTr::DBRow* row = levtr->read(id); if (!row) return 0; // Fill cache pair::iterator, bool> res = cache.insert(make_pair(id, Item(*row))); return &(res.first->second); } bool to_rec(int id, Record& rec) { const Item* i = get(id); if (!i) return 0; i->to_record(rec); return true; } Level to_level(int id) const { const Item* i = get(id); if (!i) return Level(); return i->level; } Trange to_trange(int id) const { const Item* i = get(id); if (!i) return Trange(); return i->trange; } msg::Context* to_msg(int id, Msg& msg) { const Item* i = get(id); if (!i) return 0; msg::Context& res = msg.obtain_context(i->level, i->trange); return &res; } void invalidate() { cache.clear(); } void dump(FILE* out) const { fprintf(out, "%zd elements in level/timerange cache:\n", cache.size()); for (map::const_iterator i = cache.begin(); i != cache.end(); ++i) { stringstream str; str << i->second.level; str << " "; str << i->second.trange; fprintf(out, " %d: %s\n", i->first, str.str().c_str()); } } }; std::unique_ptr LevTrCache::create(LevTr& levtr) { // TODO: check env vars to select alternate caching implementations, such // as a hit/miss that queries single items from the DB when not in cache return unique_ptr(new MapLevTrCache(levtr)); } } } } dballe-7.7/dballe/db/sql/internals.h0000644000175000017500000000374312652630043014322 00000000000000/* * db/sql/internals - Support structures not part of any public API * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include #include namespace dballe { namespace db { namespace sql { /// Store a list of attributes to be inserted/updated in the database struct AttributeList : public std::vector> { void add(wreport::Varcode code, const char* value) { push_back(std::make_pair(code, value)); } /// Get a value by code, returns nullptr if not found const char* get(wreport::Varcode code) const { for (const_iterator i = begin(); i != end(); ++i) if (i->first == code) return i->second; return nullptr; } /** * Get a value by code, returns nullptr if not found, removes it from the * AttributeList */ const char* pop(wreport::Varcode code) { const char* res = nullptr; for (iterator i = begin(); i != end(); ++i) { if (i->first == code) { res = i->second; i->second = nullptr; break; } } while (!empty() && back().second == nullptr) pop_back(); return res; } }; } } } dballe-7.7/dballe/db/sql/repinfo-test.cc0000644000175000017500000000777712652630043015113 00000000000000#include "db/tests.h" #include "db/v6/db.h" #include "db/sql.h" #include "db/sql/driver.h" #include "db/sql/repinfo.h" #include "config.h" using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace std; using namespace wreport; namespace { struct Fixture : DriverFixture { using DriverFixture::DriverFixture; unique_ptr repinfo; void reset_repinfo() { if (conn->has_table("repinfo")) driver->exec_no_data("DELETE FROM repinfo"); switch (format) { case V5: throw error_unimplemented("v5 db is not supported"); case V6: repinfo = driver->create_repinfov6(); break; default: throw error_consistency("cannot test repinfo on the current DB format"); } int added, deleted, updated; repinfo->update(nullptr, &added, &deleted, &updated); } void test_setup() { DriverFixture::test_setup(); reset_repinfo(); } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { // Test simple queries add_method("query", [](Fixture& f) { auto& ri = *f.repinfo; wassert(actual(ri.get_id("synop")) == 1); wassert(actual(ri.get_id("generic")) == 255); wassert(actual(ri.get_rep_memo(1)) == "synop"); wassert(actual(ri.get_priority(199)) == INT_MAX); }); // Test update add_method("update", [](Fixture& f) { auto& ri = *f.repinfo; wassert(actual(ri.get_id("synop")) == 1); int added, deleted, updated; ri.update(NULL, &added, &deleted, &updated); wassert(actual(added) == 0); wassert(actual(deleted) == 0); wassert(actual(updated) == 13); wassert(actual(ri.get_id("synop")) == 1); }); // Test update from a file that was known to fail add_method("fail", [](Fixture& f) { auto& ri = *f.repinfo; wassert(actual(ri.get_id("synop")) == 1); int added, deleted, updated; ri.update((string(getenv("DBA_TESTDATA")) + "/test-repinfo1.csv").c_str(), &added, &deleted, &updated); wassert(actual(added) == 3); wassert(actual(deleted) == 11); wassert(actual(updated) == 2); wassert(actual(ri.get_id("synop")) == 1); wassert(actual(ri.get_id("FIXspnpo")) == 201); }); // Test update from a file with a negative priority add_method("fail1", [](Fixture& f) { auto& ri = *f.repinfo; int id = ri.get_id("generic"); wassert(actual(ri.get_priority(id)) == 1000); int added, deleted, updated; wassert(ri.update((string(getenv("DBA_TESTDATA")) + "/test-repinfo2.csv").c_str(), &added, &deleted, &updated)); wassert(actual(added) == 3); wassert(actual(deleted) == 11); wassert(actual(updated) == 2); wassert(actual(ri.get_priority(id)) == -5); }); // Test automatic repinfo creation add_method("fail2", [](Fixture& f) { auto& ri = *f.repinfo; int id = ri.obtain_id("foobar"); wassert(actual(id) > 0); wassert(actual(ri.get_rep_memo(id)) == "foobar"); wassert(actual(ri.get_priority(id)) == 1001); id = ri.obtain_id("barbaz"); wassert(actual(id) > 0); wassert(actual(ri.get_rep_memo(id)) == "barbaz"); wassert(actual(ri.get_priority(id)) == 1002); }); } }; Tests test_sqlite("db_sql_repinfo_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests test_odbc("db_sql_repinfo_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests test_psql("db_sql_repinfo_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests test_mysql("db_sql_repinfo_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/sql/driver.h0000644000175000017500000001025312652630043013610 00000000000000/* * db/sql/driver - db-independent functions * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQL_DRIVER_H #define DBALLE_DB_SQL_DRIVER_H /** @file * @ingroup db * * Attribute table management used by the db module. */ #include #include #include #include #include #include #include namespace dballe { namespace db { struct Connection; struct Transaction; namespace v6 { struct QueryBuilder; } namespace sql { struct Repinfo; struct Station; struct LevTr; struct DataV6; struct AttrV6; /// Query results from SQL output struct SQLRecordV6 { int out_lat; int out_lon; char out_ident[64]; int out_ident_size; // -1 for NULL wreport::Varcode out_varcode; Datetime out_datetime; Datetime out_datetimemax; char out_value[255]; int out_rep_cod; int out_ana_id; int out_id_ltr; int out_id_data; int priority; /** * Checks true if ana_id, id_ltr, datetime and varcode are the same in * both records * * @returns true if they match, false if they are different */ bool querybest_fields_are_the_same(const SQLRecordV6& r); /// Dump the record as a single line to the given output stream void dump(FILE* out); }; struct Driver { public: virtual ~Driver(); /// Run a SQL query that is expected to return no data virtual void exec_no_data(const std::string& query) = 0; /// Precompiled queries to manipulate the repinfo table virtual std::unique_ptr create_repinfov6() = 0; /// Precompiled queries to manipulate the station table virtual std::unique_ptr create_stationv6() = 0; /// Precompiled queries to manipulate the levtr table virtual std::unique_ptr create_levtrv6() = 0; /// Precompiled queries to manipulate the data table virtual std::unique_ptr create_datav6() = 0; /// Precompiled queries to manipulate the attr table virtual std::unique_ptr create_attrv6() = 0; /** * Run a query on the given statement, returning results as SQLRecordV6 objects * * SQLRecordV6 is filled with the output variables according to which sel_* is true. * * Query will dispatch to the right connector routines for the query, based on * the actual implementation of stm. */ virtual void run_built_query_v6(const v6::QueryBuilder& qb, std::function dest) = 0; /// Create all missing tables for a DB with the given format void create_tables(db::Format format); /// Create all missing tables for V6 databases virtual void create_tables_v6() = 0; /// Delete all existing tables for a DB with the given format void delete_tables(db::Format format); /// Delete all existing tables for V6 databases virtual void delete_tables_v6() = 0; /// Empty all tables for a DB with the given format void remove_all(db::Format format); /// Empty all tables for V6 databases, assuming that they exist, without touching the repinfo table virtual void remove_all_v6(); /// Perform database cleanup/maintenance on v6 databases virtual void vacuum_v6() = 0; /// Outputs to stderr an explanation of the given query virtual void explain(const std::string& query); /// Create a Driver for this connection static std::unique_ptr create(Connection& conn); }; } } } #endif dballe-7.7/dballe/db/sql/station.cc0000644000175000017500000000210412652630043014130 00000000000000/* * db/station - station table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "station.h" #include "dballe/db/odbc/station.h" #include "dballe/db/odbc/internals.h" using namespace wreport; using namespace dballe::db; using namespace std; namespace dballe { namespace db { namespace sql { Station::~Station() { } } } } dballe-7.7/dballe/db/sql/datav6-test.cc0000644000175000017500000001412612652630043014620 00000000000000#include "db/tests.h" #include "db/v6/db.h" #include "db/sql.h" #include "db/sql/repinfo.h" #include "db/sql/station.h" #include "db/sql/levtr.h" #include "db/sql/datav6.h" #include "config.h" using namespace dballe; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct Fixture : DriverFixture { using DriverFixture::DriverFixture; unique_ptr data; void reset_data() { auto st = driver->create_stationv6(); auto lt = driver->create_levtrv6(); int added, deleted, updated; driver->create_repinfov6()->update(nullptr, &added, &deleted, &updated); // Insert a mobile station wassert(actual(st->obtain_id(4500000, 1100000, "ciao")) == 1); // Insert a fixed station wassert(actual(st->obtain_id(4600000, 1200000)) == 2); // Insert a lev_tr wassert(actual(lt->obtain_id(Level(1, 2, 0, 3), Trange(4, 5, 6))) == 1); // Insert another lev_tr wassert(actual(lt->obtain_id(Level(2, 3, 1, 4), Trange(5, 6, 7))) == 2); } void test_setup() { DriverFixture::test_setup(); data = driver->create_datav6(); reset_data(); } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("insert", [](Fixture& f) { using namespace dballe::db::sql; auto& da = *f.data; auto t = f.conn->transaction(); Var var(varinfo(WR_VAR(0, 1, 2))); auto insert_sample1 = [&](bulk::InsertV6& vars, int value, DataV6::UpdateMode update) { vars.id_station = 1; vars.id_report = 1; vars.datetime = Datetime(2001, 2, 3, 4, 5, 6); var.seti(value); vars.add(&var, 1); da.insert(*t, vars, update); }; // Insert a datum { bulk::InsertV6 vars; insert_sample1(vars, 123, DataV6::ERROR); wassert(actual(vars[0].id_data) == 1); wassert(actual(vars[0].needs_insert()).isfalse()); wassert(actual(vars[0].inserted()).istrue()); wassert(actual(vars[0].needs_update()).isfalse()); wassert(actual(vars[0].updated()).isfalse()); } // Insert another datum { bulk::InsertV6 vars; vars.id_station = 2; vars.id_report = 2; vars.datetime = Datetime(2002, 3, 4, 5, 6, 7); Var var(varinfo(WR_VAR(0, 1, 2)), 234); vars.add(&var, 2); da.insert(*t, vars, DataV6::ERROR); wassert(actual(vars[0].id_data) == 2); wassert(actual(vars[0].needs_insert()).isfalse()); wassert(actual(vars[0].inserted()).istrue()); wassert(actual(vars[0].needs_update()).isfalse()); wassert(actual(vars[0].updated()).isfalse()); } // Reinsert the first datum: it should find its ID and do nothing { bulk::InsertV6 vars; insert_sample1(vars, 123, DataV6::ERROR); wassert(actual(vars[0].id_data) == 1); wassert(actual(vars[0].needs_insert()).isfalse()); wassert(actual(vars[0].inserted()).isfalse()); wassert(actual(vars[0].needs_update()).isfalse()); wassert(actual(vars[0].updated()).isfalse()); } // Reinsert the first datum, with a different value and ignore // overwrite: it should find its ID and do nothing { bulk::InsertV6 vars; insert_sample1(vars, 125, DataV6::IGNORE); wassert(actual(vars[0].id_data) == 1); wassert(actual(vars[0].needs_insert()).isfalse()); wassert(actual(vars[0].inserted()).isfalse()); wassert(actual(vars[0].needs_update()).istrue()); wassert(actual(vars[0].updated()).isfalse()); } // Reinsert the first datum, with a different value and overwrite: // it should find its ID and update it { bulk::InsertV6 vars; insert_sample1(vars, 125, DataV6::UPDATE); wassert(actual(vars[0].id_data) == 1); wassert(actual(vars[0].needs_insert()).isfalse()); wassert(actual(vars[0].inserted()).isfalse()); wassert(actual(vars[0].needs_update()).isfalse()); wassert(actual(vars[0].updated()).istrue()); } // Reinsert the first datum, with the same value and error on // overwrite: it should find its ID and do nothing, because the value // does not change. { bulk::InsertV6 vars; insert_sample1(vars, 125, DataV6::ERROR); wassert(actual(vars[0].id_data) == 1); wassert(actual(vars[0].needs_insert()).isfalse()); wassert(actual(vars[0].inserted()).isfalse()); wassert(actual(vars[0].needs_update()).isfalse()); wassert(actual(vars[0].updated()).isfalse()); } // Reinsert the first datum, with a different value and error on // overwrite: it should throw an error { bulk::InsertV6 vars; try { insert_sample1(vars, 126, DataV6::IGNORE); wassert(actual(false).isfalse()); } catch (std::exception& e) { wassert(actual(e.what()).contains("refusing to overwrite existing data")); } } t->commit(); }); } }; Tests tg1("db_sql_data_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg2("db_sql_data_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg3("db_sql_data_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg4("db_sql_data_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/sql/levtr-test.cc0000644000175000017500000000257712652630043014576 00000000000000#include "db/tests.h" #include "db/v6/db.h" #include "db/sql.h" #include "db/sql/levtr.h" #include "config.h" using namespace dballe; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct Fixture : DriverFixture { using DriverFixture::DriverFixture; unique_ptr levtr; void reset_levtr() { if (conn->has_table("levtr")) driver->exec_no_data("DELETE FROM levtr"); levtr = driver->create_levtrv6(); } void test_setup() { DriverFixture::test_setup(); reset_levtr(); } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("insert", [](Fixture& f) { auto& lt = *f.levtr; // Insert a lev_tr wassert(actual(lt.obtain_id(Level(1, 2, 0, 3), Trange(4, 5, 6))) == 1); // Insert another lev_tr wassert(actual(lt.obtain_id(Level(2, 3, 1, 4), Trange(5, 6, 7))) == 2); }); } }; Tests test_sqlite("db_sql_levtr_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests test_odbc("db_sql_levtr_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests test_psql("db_sql_levtr_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests test_mysql("db_sql_levtr_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/sql/datav6.cc0000644000175000017500000001147012652630043013642 00000000000000/* * db/sql/datav6 - interface to the V6 data table * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "datav6.h" #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace sql { DataV6::~DataV6() {} namespace bulk { void Item::format_flags(char* dest) const { dest[0] = needs_update() ? 'u' : '-', dest[1] = updated() ? 'U' : '-', dest[2] = needs_insert() ? 'i' : '-', dest[3] = inserted() ? 'I' : '-', dest[4] = 0; } AnnotateVarsV6::AnnotateVarsV6(InsertV6& vars) : vars(vars) { std::sort(vars.begin(), vars.end()); iter = vars.begin(); } bool AnnotateVarsV6::annotate(int id_data, int id_levtr, Varcode code, const char* value) { //fprintf(stderr, "ANNOTATE "); while (iter != vars.end()) { //fprintf(stderr, "id_data: %d/%d id_levtr: %d/%d varcode: %d/%d value: %s/%s: ", id_data, iter->id_data, id_levtr, iter->id_levtr, code, iter->var->code(), value, iter->var->value()); // This variable is not on our list: stop here and wait for a new one if (id_levtr < iter->id_levtr) { //fprintf(stderr, "levtr lower than ours, wait for next\n"); return true; } // iter points to a variable that is not currently in the DB if (id_levtr > iter->id_levtr) { //fprintf(stderr, "levtr higher than ours, insert this\n"); do_insert = true; iter->set_needs_insert(); ++iter; continue; } // id_levtr is the same // This variable is not on our list: stop here and wait for a new one if (code < iter->var->code()) { //fprintf(stderr, "varcode lower than ours, wait for next\n"); return true; } // iter points to a variable that is not currently in the DB if (code > iter->var->code()) { //fprintf(stderr, "varcode higher than ours, insert this\n"); do_insert = true; iter->set_needs_insert(); ++iter; continue; } // iter points to a variable that is also in the DB // Annotate with the ID //fprintf(stderr, "id_data=%d ", id_data); iter->id_data = id_data; // If the value is different, we need to update if (strcmp(value, iter->var->enqc()) != 0) { //fprintf(stderr, "needs_update "); iter->set_needs_update(); do_update = true; } // We processed this variable: stop here and wait for a new one ++iter; //fprintf(stderr, "wait for next\n"); return true; } // We have no more variables to consider: signal the caller that they can // stop iterating if they wish. //fprintf(stderr, "done.\n"); return false; } void AnnotateVarsV6::annotate_end() { // Mark all remaining variables as needing insert for ( ; iter != vars.end(); ++iter) { //fprintf(stderr, "LEFTOVER: id_levtr: %d varcode: %d value: %s\n", iter->id_levtr, iter->var->code(), iter->var->value()); iter->set_needs_insert(); do_insert = true; } } void AnnotateVarsV6::dump(FILE* out) const { fprintf(out, "Needs insert: %d, needs update: %d\n", do_insert, do_update); vars.dump(out); } void VarV6::dump(FILE* out) const { char flags[5]; format_flags(flags); fprintf(out, "ltr:%d data:%d flags:%s %01d%02d%03d(%d): %s\n", id_levtr, id_data, flags, WR_VAR_F(var->code()), WR_VAR_X(var->code()), WR_VAR_Y(var->code()), (int)(var->code()), var->isset() ? var->enqc() : "(null)"); } void InsertV6::dump(FILE* out) const { fprintf(out, "ID station: %d, ID report: %d, datetime: %04d-%02d-%02d %02d:%02d:%02d\n", id_station, id_report, datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second); for (unsigned i = 0; i < size(); ++i) { fprintf(out, "%3u/%3zd: ", i, size()); (*this)[i].dump(out); } } } } } } dballe-7.7/dballe/db/sql/attrv6.cc0000644000175000017500000000756212652630043013712 00000000000000#include "attrv6.h" #include "internals.h" #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace sql { AttrV6::~AttrV6() {} void AttrV6::insert_attributes(Transaction& t, int id_data, const wreport::Var& var, UpdateMode update_mode) { bulk::InsertAttrsV6 attrs; attrs.add_all(var, id_data); if (attrs.empty()) return; insert(t, attrs, update_mode); } namespace bulk { void InsertAttrsV6::add_all(const wreport::Var& var, int id_data) { for (const Var* attr = var.next_attr(); attr != NULL; attr = attr->next_attr()) if (attr->isset()) emplace_back(attr, id_data); } AnnotateAttrsV6::AnnotateAttrsV6(InsertAttrsV6& attrs) : attrs(attrs) { std::sort(attrs.begin(), attrs.end()); iter = attrs.begin(); } bool AnnotateAttrsV6::annotate(int id_data, Varcode code, const char* value) { //fprintf(stderr, "ANNOTATE "); while (iter != attrs.end()) { //fprintf(stderr, "id_data: %d/%d id_levtr: %d/%d varcode: %d/%d value: %s/%s: ", id_data, iter->id_data, id_levtr, iter->id_levtr, code, iter->var->code(), value, iter->var->value()); // This attribute is not on our list: stop here and wait for a new one if (id_data < iter->id_data) { //fprintf(stderr, "levtr lower than ours, wait for next\n"); return true; } // iter points to a attribute that is not currently in the DB if (id_data > iter->id_data) { //fprintf(stderr, "levtr higher than ours, insert this\n"); do_insert = true; iter->set_needs_insert(); ++iter; continue; } // id_levtr is the same // This attribute is not on our list: stop here and wait for a new one if (code < iter->attr->code()) { //fprintf(stderr, "varcode lower than ours, wait for next\n"); return true; } // iter points to a attribute that is not currently in the DB if (code > iter->attr->code()) { //fprintf(stderr, "varcode higher than ours, insert this\n"); do_insert = true; iter->set_needs_insert(); ++iter; continue; } // iter points to an attribute that is also in the DB // If the value is different, we need to update if (strcmp(value, iter->attr->enqc()) != 0) { //fprintf(stderr, "needs_update "); iter->set_needs_update(); do_update = true; } // We processed this attribute: stop here and wait for a new one ++iter; //fprintf(stderr, "wait for next\n"); return true; } // We have no more attribute to consider: signal the caller that they can // stop iterating if they wish. //fprintf(stderr, "done.\n"); return false; } void AnnotateAttrsV6::annotate_end() { // Mark all remaining attribute as needing insert for ( ; iter != attrs.end(); ++iter) { //fprintf(stderr, "LEFTOVER: id_levtr: %d varcode: %d value: %s\n", iter->id_levtr, iter->var->code(), iter->var->value()); iter->set_needs_insert(); do_insert = true; } } void AnnotateAttrsV6::dump(FILE* out) const { fprintf(out, "Needs insert: %d, needs update: %d\n", do_insert, do_update); attrs.dump(out); } void AttrV6::dump(FILE* out) const { char flags[5]; format_flags(flags); fprintf(out, "flags:%s %01d%02d%03d(%d): %s\n", flags, WR_VAR_F(attr->code()), WR_VAR_X(attr->code()), WR_VAR_Y(attr->code()), (int)(attr->code()), attr->isset() ? attr->enqc() : "(null)"); } void InsertAttrsV6::dump(FILE* out) const { for (unsigned i = 0; i < size(); ++i) { fprintf(out, "%3u/%3zd: ", i, size()); (*this)[i].dump(out); } } } } } } dballe-7.7/dballe/db/sql/attrv6-test.cc0000644000175000017500000001642112652630043014661 00000000000000#include "db/tests.h" #include "db/v6/db.h" #include "db/sql.h" #include "db/sql/repinfo.h" #include "db/sql/station.h" #include "db/sql/levtr.h" #include "db/sql/datav6.h" #include "db/sql/attrv6.h" #include "config.h" using namespace dballe; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct Fixture : DriverFixture { using DriverFixture::DriverFixture; unique_ptr attr; void reset_attr() { using namespace dballe::db::sql; auto st = driver->create_stationv6(); auto lt = driver->create_levtrv6(); auto da = driver->create_datav6(); int added, deleted, updated; driver->create_repinfov6()->update(nullptr, &added, &deleted, &updated); // Insert a mobile station wassert(actual(st->obtain_id(4500000, 1100000, "ciao")) == 1); // Insert a fixed station wassert(actual(st->obtain_id(4600000, 1200000)) == 2); // Insert a lev_tr wassert(actual(lt->obtain_id(Level(1, 2, 0, 3), Trange(4, 5, 6))) == 1); // Insert another lev_tr wassert(actual(lt->obtain_id(Level(2, 3, 1, 4), Trange(5, 6, 7))) == 2); auto t = conn->transaction(); // Insert a datum { bulk::InsertV6 vars; vars.id_station = 1; vars.id_report = 1; vars.datetime = Datetime(2001, 2, 3, 4, 5, 6); Var var(varinfo(WR_VAR(0, 1, 2)), 123); vars.add(&var, 1); da->insert(*t, vars, DataV6::ERROR); } // Insert another datum { bulk::InsertV6 vars; vars.id_station = 2; vars.id_report = 2; vars.datetime = Datetime(2002, 3, 4, 5, 6, 7); Var var(varinfo(WR_VAR(0, 1, 2)), 234); vars.add(&var, 2); da->insert(*t, vars, DataV6::ERROR); } t->commit(); } void test_setup() { DriverFixture::test_setup(); attr = driver->create_attrv6(); reset_attr(); } Var query(int id_data, unsigned expected_attr_count) { Var res(varinfo(WR_VAR(0, 12, 101))); unsigned count = 0; attr->read(id_data, [&](unique_ptr attr) { res.seta(auto_ptr(attr.release())); ++count; }); wassert(actual(count) == expected_attr_count); return res; } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("insert", [](Fixture& f) { using namespace dballe::db::sql; auto& at = *f.attr; auto t = f.conn->transaction(); Var var1(varinfo(WR_VAR(0, 12, 101)), 280.0); var1.seta(newvar(WR_VAR(0, 33, 7), 50)); Var var2(varinfo(WR_VAR(0, 12, 101)), 280.0); var2.seta(newvar(WR_VAR(0, 33, 7), 75)); // Insert two attributes { bulk::InsertAttrsV6 attrs; attrs.add_all(var1, 1); at.insert(*t, attrs, AttrV6::ERROR); wassert(actual(attrs.size()) == 1); wassert(actual(attrs[0].needs_insert()).isfalse()); wassert(actual(attrs[0].inserted()).istrue()); wassert(actual(attrs[0].needs_update()).isfalse()); wassert(actual(attrs[0].updated()).isfalse()); } { bulk::InsertAttrsV6 attrs; attrs.add_all(var2, 2); at.insert(*t, attrs, AttrV6::ERROR); wassert(actual(attrs.size()) == 1); wassert(actual(attrs[0].needs_insert()).isfalse()); wassert(actual(attrs[0].inserted()).istrue()); wassert(actual(attrs[0].needs_update()).isfalse()); wassert(actual(attrs[0].updated()).isfalse()); } // Reinsert the first attribute: it should work, doing no insert/update queries { bulk::InsertAttrsV6 attrs; attrs.add_all(var1, 1); at.insert(*t, attrs, AttrV6::IGNORE); wassert(actual(attrs.size()) == 1); wassert(actual(attrs[0].needs_insert()).isfalse()); wassert(actual(attrs[0].inserted()).isfalse()); wassert(actual(attrs[0].needs_update()).isfalse()); wassert(actual(attrs[0].updated()).isfalse()); } // Reinsert the second attribute: it should work, doing no insert/update queries { bulk::InsertAttrsV6 attrs; attrs.add_all(var2, 2); at.insert(*t, attrs, AttrV6::UPDATE); wassert(actual(attrs.size()) == 1); wassert(actual(attrs[0].needs_insert()).isfalse()); wassert(actual(attrs[0].inserted()).isfalse()); wassert(actual(attrs[0].needs_update()).isfalse()); wassert(actual(attrs[0].updated()).isfalse()); } // Load the attributes for the first variable { Var var(f.query(1, 1)); wassert(actual(var.next_attr()->code()) == WR_VAR(0, 33, 7)); wassert(actual(*var.next_attr()) == 50); } // Load the attributes for the second variable { Var var(f.query(2, 1)); wassert(actual(var.next_attr()->code()) == WR_VAR(0, 33, 7)); wassert(actual(*var.next_attr()) == 75); } // Update both values { bulk::InsertAttrsV6 attrs; attrs.add_all(var2, 1); at.insert(*t, attrs, AttrV6::UPDATE); wassert(actual(attrs.size()) == 1); wassert(actual(attrs[0].needs_insert()).isfalse()); wassert(actual(attrs[0].inserted()).isfalse()); wassert(actual(attrs[0].needs_update()).isfalse()); wassert(actual(attrs[0].updated()).istrue()); } { bulk::InsertAttrsV6 attrs; attrs.add_all(var1, 2); at.insert(*t, attrs, AttrV6::UPDATE); wassert(actual(attrs.size()) == 1); wassert(actual(attrs[0].needs_insert()).isfalse()); wassert(actual(attrs[0].inserted()).isfalse()); wassert(actual(attrs[0].needs_update()).isfalse()); wassert(actual(attrs[0].updated()).istrue()); } // Load the attributes again to verify that they changed { Var var(f.query(1, 1)); wassert(actual(var.next_attr()->code()) == WR_VAR(0, 33, 7)); wassert(actual(*var.next_attr()) == 75); } { Var var(f.query(2, 1)); wassert(actual(var.next_attr()->code()) == WR_VAR(0, 33, 7)); wassert(actual(*var.next_attr()) == 50); } // TODO: test a mix of update and insert }); } }; Tests tg1("db_sql_attr_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg2("db_sql_attr_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg3("db_sql_attr_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg4("db_sql_attr_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/sql/station.h0000644000175000017500000000470012652630043013776 00000000000000/* * db/station - station table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQL_STATION_H #define DBALLE_DB_SQL_STATION_H /** @file * @ingroup db * * Station table management used by the db module. */ #include #include namespace wreport { struct Var; } namespace dballe { struct Record; namespace db { struct Connection; namespace sql { struct Station { public: /// Instantiate a Station object for this connection //static std::unique_ptr create(Connection& conn); virtual ~Station(); /** * Get the station ID given latitude, longitude and mobile identifier. * * It throws an exception if it does not exist. * * @return * Resulting ID of the station */ virtual int get_id(int lat, int lon, const char* ident=NULL) = 0; /** * Get the station ID given latitude, longitude and mobile identifier. * * It creates the station record if it does not exist. * * @return * Resulting ID of the station */ virtual int obtain_id(int lat, int lon, const char* ident=NULL, bool* inserted=NULL) = 0; /** * Dump the entire contents of the table to an output stream */ virtual void dump(FILE* out) = 0; /** * Export station variables */ virtual void get_station_vars(int id_station, int id_report, std::function)> dest) = 0; /** * Add all station variables (without attributes) to rec. * * If the same variable exists in many different networks, the one with the * highest priority will be used. */ virtual void add_station_vars(int id_station, Record& rec) = 0; }; } } } #endif dballe-7.7/dballe/db/sql/attrv6.h0000644000175000017500000000644112652630043013547 00000000000000/* * db/sql/attrv6 - v6 implementation of attr table * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQL_ATTRV6_H #define DBALLE_DB_SQL_ATTRV6_H #include #include #include #include #include #include namespace dballe { struct Record; namespace db { namespace sql { struct AttributeList; namespace bulk { struct InsertAttrsV6; } /** * Precompiled queries to manipulate the attr table */ struct AttrV6 { public: enum UpdateMode { UPDATE, IGNORE, ERROR, }; virtual ~AttrV6(); /// Insert all attributes of the given variable void insert_attributes(Transaction& t, int id_data, const wreport::Var& var, UpdateMode update_mode=UPDATE); /// Bulk attribute insert virtual void insert(Transaction& t, sql::bulk::InsertAttrsV6& vars, UpdateMode update_mode=UPDATE) = 0; /** * Load from the database all the attributes for var * * @param var * wreport::Var to which the resulting attributes will be added * @return * The error indicator for the function (See @ref error.h) */ virtual void read(int id_data, std::function)> dest) = 0; /** * Dump the entire contents of the table to an output stream */ virtual void dump(FILE* out) = 0; }; namespace bulk { /** * Workflow information about an attribute variable listed for bulk * insert/update */ struct AttrV6 : public Item { int id_data; const wreport::Var* attr; AttrV6(const wreport::Var* attr, int id_data=-1) : id_data(id_data), attr(attr) { } bool operator<(const AttrV6& v) const { if (int d = id_data - v.id_data) return d < 0; return attr->code() < v.attr->code(); } void dump(FILE* out) const; }; struct InsertAttrsV6 : public std::vector { void add(const wreport::Var* attr, int id_data) { emplace_back(attr, id_data); } // Add all attributes of the given variable void add_all(const wreport::Var& var, int id_data); void dump(FILE* out) const; }; /** * Helper class for annotating InsertV6 variables with the current status of * the database. */ struct AnnotateAttrsV6 { InsertAttrsV6& attrs; InsertAttrsV6::iterator iter; bool do_insert = false; bool do_update = false; AnnotateAttrsV6(InsertAttrsV6& attrs); bool annotate(int id_data, wreport::Varcode code, const char* value); void annotate_end(); void dump(FILE* out) const; }; } } } } #endif dballe-7.7/dballe/db/sql/datav6.h0000644000175000017500000001005012652630043013475 00000000000000/* * db/sql/datav6 - interface to the V6 data table * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQL_DATAV6_H #define DBALLE_DB_SQL_DATAV6_H /** @file * @ingroup db * * Attribute table management used by the db module. */ #include #include #include #include #include namespace dballe { struct Record; namespace db { struct Connection; struct Transaction; namespace v6 { struct QueryBuilder; } namespace sql { namespace bulk { struct InsertV6; } /** * Precompiled query to manipulate the data table */ struct DataV6 { public: enum UpdateMode { UPDATE, IGNORE, ERROR, }; virtual ~DataV6(); /// Bulk variable insert virtual void insert(Transaction& t, bulk::InsertV6& vars, UpdateMode update_mode=UPDATE) = 0; /// Run the query to delete all records selected by the given QueryBuilder virtual void remove(const v6::QueryBuilder& qb) = 0; /// Dump the entire contents of the table to an output stream virtual void dump(FILE* out) = 0; }; namespace bulk { struct Item { static const unsigned FLAG_NEEDS_UPDATE = 1 << 0; static const unsigned FLAG_UPDATED = 1 << 1; static const unsigned FLAG_NEEDS_INSERT = 1 << 2; static const unsigned FLAG_INSERTED = 1 << 3; unsigned flags = 0; bool needs_update() const { return flags & FLAG_NEEDS_UPDATE; } bool updated() const { return flags & FLAG_UPDATED; } bool needs_insert() const { return flags & FLAG_NEEDS_INSERT; } bool inserted() const { return flags & FLAG_INSERTED; } void set_needs_update() { flags |= FLAG_NEEDS_UPDATE; } void set_updated() { flags = (flags & ~FLAG_NEEDS_UPDATE) | FLAG_UPDATED; } void set_needs_insert() { flags |= FLAG_NEEDS_INSERT; } void set_inserted() { flags = (flags & ~FLAG_NEEDS_INSERT) | FLAG_INSERTED; } /** * Format flags in the first 4 characters of dest. * * It adds a trailing 0, so dest should be at least 5 bytes long. */ void format_flags(char* dest) const; }; /** * Workflow information about a variable listed for bulk insert/update */ struct VarV6 : public Item { int id_levtr; int id_data; const wreport::Var* var; VarV6(const wreport::Var* var, int id_levtr=-1, int id_data=-1) : id_levtr(id_levtr), id_data(id_data), var(var) { } bool operator<(const VarV6& v) const { if (int d = id_levtr - v.id_levtr) return d < 0; return var->code() < v.var->code(); } void dump(FILE* out) const; }; /** * Input for a bulk insert of a lot of variables sharing the same context * information. */ struct InsertV6 : public std::vector { int id_station; int id_report; Datetime datetime; void add(const wreport::Var* var, int id_levtr) { emplace_back(var, id_levtr); } void dump(FILE* out) const; }; /** * Helper class for annotating InsertV6 variables with the current status of * the database. */ struct AnnotateVarsV6 { InsertV6& vars; InsertV6::iterator iter; bool do_insert = false; bool do_update = false; AnnotateVarsV6(InsertV6& vars); bool annotate(int id_data, int id_levtr, wreport::Varcode code, const char* value); void annotate_end(); void dump(FILE* out) const; }; } } } } #endif dballe-7.7/dballe/db/db-query-parse-bench.cc0000644000175000017500000002107012652630043015570 00000000000000/* * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "dballe/db/bench.h" #include "dballe/file.h" #include "dballe/core/query.h" #include "dballe/msg/msg.h" #include "dballe/msg/codec.h" #include #include using namespace dballe; using namespace std; using namespace wreport; namespace { #if 0 template struct Samples : public std::map> { unsigned seed = 0; // Return a random number in the domain [min, max) int rnd(int min, int max) { int r = rand_r(&seed); return min + (int)((double)(max - min) * r / RAND_MAX); } // Add a sample value for a key void add(const std::string& key, const T& sample) { (*this)[key].push_back(sample); } // Return a random key const std::string& get_key() const { int r = rnd(0, size()); return *(begin() + r); } // Return a random value for a key const T& get_val(const std::string& key) const { auto i = find(key); if (i == end()) error_consistency::throwf("no samples registered for %s", key.c_str()); return i->second[rnd(0, i->second.size())]; } }; struct Generator { Samples ints; Samples strings; Samples coords; Samples datetimes; Samples levels; Samples tranges; Generator() { ints.add("ana_id", 1); ints.add("ana_id", 2); ints.add("ana_id", 3); ints.add("ana_id", 4); ints.add("ana_id", 5); ints.add("priority", 1); ints.add("priority", 10); ints.add("priority", 100); } int ana_id = MISSING_INT; int prio_min = MISSING_INT; int prio_max = MISSING_INT; std::string rep_memo; int mobile = MISSING_INT; bool has_ident = false; std::string ident; Coords coords_min; Coords coords_max; Datetime datetime_min; Datetime datetime_max; Level level; Trange trange; std::set varcodes; std::string query; std::string ana_filter; std::string data_filter; std::string attr_filter; int limit = MISSING_INT; int block = MISSING_INT; int station = MISSING_INT; int data_id = MISSING_INT; bool query_station_vars = false; }; #endif struct Data { vector> data; const int Q_ANA_ID = 0; const int Q_LATLON = 1; const int Q_MOBILE = 2; const int Q_ANAFILTER = 3; const int Q_BLOCKSTATION = 4; const int Q_PRIO = 5; const int Q_REPMEMO = 6; const int Q_VAR = 7; const int Q_DATETIME = 8; const int Q_LEVEL = 9; const int Q_TRANGE = 10; const int Q_QBEST = 11; const int Q_DATA_ID = 12; const int Q_DATA_FILTER = 13; const int Q_ATTR_FILTER = 14; Data() { data.push_back({"ana_id=1"}); data.push_back({ "latmin=40, latmax=45", "lonmin=10, lonmax=15", "lonmin=15, lonmax=10", "latmin=40, latmax=45, lonmin=10, lonmax=15", "latmin=40, latmax=45, lonmin=15, lonmax=10", "lat=11, lon=45", }); data.push_back({ "mobile=0", "mobile=1, ident=antani", }); data.push_back({"ana_filter=B07004=1000"}); data.push_back({ "block=16", "block=16, station=404", }); data.push_back({ "priority=100", "priomin=1, priomax=100", }); data.push_back({"rep_memo=synop"}); data.push_back({ "var=B12101", "varlist=B11101,B12101,B12103", }); data.push_back({ "year=1945, month=4, day=25, hour=12, min=30, sec=45", "yearmin=1945, yearmax=2000", }); data.push_back({"leveltype1=1, l1=1000, leveltype2=1, l2=2000"}); data.push_back({"pindicator=1, p1=2, p2=3"}); data.push_back({"query=best"}); data.push_back({"context_id=42"}); data.push_back({"data_filter=B12101>278.15"}); data.push_back({"attr_filter=B33007>50"}); } string build(const vector& items, const vector& cur) const { string res; for (unsigned i = 0; i < items.size(); ++i) { if (cur[i] == -1) continue; if (!res.empty()) res += ", "; res += data[items[i]][cur[i]]; } return res; } // Return false if cur cannot be implemented anymore bool increment(const vector& items, vector& cur, unsigned pos=0) const { if (pos >= items.size()) return false; ++cur[pos]; if (cur[pos] >= data[items[pos]].size()) { cur[pos] = -1; return increment(items, cur, pos+1); } else { return true; } } void generate(const vector& items, std::function dest) { vector cur(items.size(), -1); while (true) { // Build a string with cur dest(build(items, cur)); // Increment cur // Break if cur is the max if (!increment(items, cur)) break; } } }; struct B : bench::DBBenchmark { vector queries_station; vector queries_sdata; vector queries_data; benchmark::Task station; benchmark::Task sdata; benchmark::Task data; B(const std::string& name) : bench::DBBenchmark::DBBenchmark(name), station(this, "station"), sdata(this, "sdata"), data(this, "data") { repetitions = 5; } void setup_main() { const int Q_ANA_ID = 0; const int Q_LATLON = 1; const int Q_MOBILE = 2; const int Q_ANAFILTER = 3; const int Q_BLOCKSTATION = 4; const int Q_PRIO = 5; const int Q_REPMEMO = 6; const int Q_VAR = 7; const int Q_DATETIME = 8; const int Q_LEVEL = 9; const int Q_TRANGE = 10; const int Q_QBEST = 11; const int Q_DATA_ID = 12; const int Q_DATA_FILTER = 13; const int Q_ATTR_FILTER = 14; unsigned count = 0; bench::DBBenchmark::setup_main(); Data d; d.generate({Q_ANA_ID, Q_LATLON, Q_MOBILE, Q_ANAFILTER, Q_BLOCKSTATION}, [&](const std::string& q) { core::Query query; query.set_from_test_string(q); queries_station.push_back(query); }); //fprintf(stderr, "%zd stations\n", queries_station.size()); count = 0; d.generate({Q_ANA_ID, Q_LATLON, Q_MOBILE, Q_ANAFILTER, Q_BLOCKSTATION, Q_PRIO, Q_REPMEMO, Q_DATA_ID, Q_DATA_FILTER, Q_ATTR_FILTER}, [&](const std::string& q) { if (count++ % 7 != 0) return; core::Query query; query.set_from_test_string(q); queries_sdata.push_back(query); }); //fprintf(stderr, "%zd sdata\n", queries_sdata.size()); count = 0; d.generate({Q_ANA_ID, Q_LATLON, Q_MOBILE, Q_ANAFILTER, Q_BLOCKSTATION, Q_PRIO, Q_REPMEMO, Q_VAR, Q_DATETIME, Q_LEVEL, Q_TRANGE, Q_QBEST, Q_DATA_ID, Q_DATA_FILTER, Q_ATTR_FILTER}, [&](const std::string& q) { if (count++ % 149 != 0) return; core::Query query; query.set_from_test_string(q); queries_data.push_back(query); }); //fprintf(stderr, "%zd data\n", queries_data.size()); } void main() override { station.collect([&]() { for (auto& q: queries_station) db->query_stations(q); }); sdata.collect([&]() { for (auto& q: queries_sdata) db->query_data(q); }); data.collect([&]() { for (auto& q: queries_data) db->query_data(q); }); } } test("db_query_parse"); } dballe-7.7/dballe/db/querybuf.h0000644000175000017500000000552012652630043013361 00000000000000/* * db/querybuf - Buffer used to build SQL queries * * Copyright (C) 2005--2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBA_DB_QUERYBUF_H #define DBA_DB_QUERYBUF_H /** @file * @ingroup db * Implementation of an efficient string buffer for composing database queries */ #include #include #include namespace dballe { /// String buffer for composing database queries struct Querybuf : public std::string { bool list_first; char list_sep[10]; /** * @param reserve * Initial preallocated size for the buffer. If this is chosen * wisely, there is no need to reallocate space while composing the * query. */ Querybuf(size_t reserve = 512); ~Querybuf(); /// Reset the querybuf to contain the empty string void clear(); /** * Begin a list of items separated by the given separator. Items are added * using append_list(). * * @param sep * The separator to add between every list item */ void start_list(const char* sep); /** * Append a formatted string to the querybuf * * @param fmt * The string to append, which will be formatted in printf style */ void appendf(const char* fmt, ...) __attribute__((format(printf, 2, 3))); /** * Append a string to the querybuf, as part of a list. * * This function will prepend str with the current list separator, unless it is * the first item added to the list. * * @param str * The string to append */ void append_list(const char* str); /** * Append a formatted string to the querybuf, as part of a list. * * This function will prepend str with the current list separator, unless it is * the first item added to the list. * * @param str * The string to append */ void append_listf(const char* fmt, ...) __attribute__((format(printf, 2, 3))); /** * Append a comma-separated list of integer varcodes parsed from a * varlist=B12101,B12013 query parameter */ void append_varlist(const std::string& varlist); /// Append a comma-separated list of integer varcodes void append_varlist(const std::set& varlist); }; } // namespace dballe #endif dballe-7.7/dballe/db/db-basic-test.cc0000644000175000017500000001614212652630043014300 00000000000000#include "config.h" #include "msg/msg.h" #include "db/tests.h" #include "db/mem/db.h" using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { // Test simple queries add_method("reset", [](Fixture& f) { // Run twice to see if it is idempotent auto& db = *f.db; db.reset(); db.reset(); }); add_method("repinfo", [](Fixture& f) { // Test repinfo-related functions auto& db = *f.db; std::map prios = db.get_repinfo_priorities(); wassert(actual(prios.find("synop") != prios.end()).istrue()); wassert(actual(prios["synop"]) == 101); int added, deleted, updated; db.update_repinfo((string(getenv("DBA_TESTDATA")) + "/test-repinfo1.csv").c_str(), &added, &deleted, &updated); wassert(actual(added) == 3); wassert(actual(deleted) == 11); wassert(actual(updated) == 2); prios = db.get_repinfo_priorities(); wassert(actual(prios.find("fixspnpo") != prios.end()).istrue()); wassert(actual(prios["fixspnpo"]) == 200); }); add_method("vacuum", [](Fixture& f) { // Just invoke vacuum auto& db = *f.db; db.vacuum(); }); add_method("simple", [](Fixture& f) { // Test remove_all auto& db = *f.db; db.remove_all(); std::unique_ptr cur = db.query_data(core::Query()); wassert(actual(cur->remaining()) == 0); // Check that it is idempotent db.remove_all(); cur = db.query_data(core::Query()); wassert(actual(cur->remaining()) == 0); // Insert something wassert(f.populate()); cur = db.query_data(core::Query()); wassert(actual(cur->remaining()) == 4); db.remove_all(); cur = db.query_data(core::Query()); wassert(actual(cur->remaining()) == 0); }); add_method("stationdata", [](Fixture& f) { // Test adding station data for different networks auto& db = *f.db; db.reset(); // Insert two values in two networks DataValues vals; vals.info.coords = Coords(12.077, 44.600); vals.info.report = "synop"; vals.info.level = Level(103, 2000); vals.info.trange = Trange::instant(); vals.info.datetime = Datetime(2014, 1, 1, 0, 0, 0); vals.values.set("B12101", 273.15); db.insert_data(vals, true, true); vals.clear_ids(); vals.info.report = "temp"; vals.values.set("B12101", 274.15); db.insert_data(vals, true, true); // Insert station names in both networks StationValues svals_camse; svals_camse.info.coords = vals.info.coords; svals_camse.info.report = "synop"; svals_camse.values.set("B01019", "Camse"); db.insert_station_data(svals_camse, true, true); StationValues svals_esmac; svals_esmac.info.coords = vals.info.coords; svals_esmac.info.report = "temp"; svals_esmac.values.set("B01019", "Esmac"); db.insert_station_data(svals_esmac, true, true); // Query back all the data auto cur = db.query_stations(core::Query()); // Check results core::Record result; if (dynamic_cast(f.db)) { // For mem databases, we get one record per (station, network) // combination wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_station_id()) == svals_esmac.info.ana_id); wassert(actual(cur->get_rep_memo()) == "temp"); cur->to_record(result); wassert(actual(result["B01019"]) == "Esmac"); wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_station_id()) == svals_camse.info.ana_id); wassert(actual(cur->get_rep_memo()) == "synop"); cur->to_record(result); wassert(actual(result["B01019"]) == "Camse"); } else { // For normal databases, we only get one record, with the station // values merged keeping values for the best networks wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_station_id()) == 1); cur->to_record(result); wassert(actual(result["B01019"]) == "Camse"); wassert(actual(cur->next()).isfalse()); } Messages msgs; db.export_msgs(core::Query(), [&](unique_ptr&& msg) { msgs.append(move(msg)); return true; }); wassert(actual(msgs.size()) == 2); //msgs.print(stderr); wassert(actual(Msg::downcast(msgs[0]).get_rep_memo_var()->enqc()) == "synop"); wassert(actual(Msg::downcast(msgs[0]).get_st_name_var()->enqc()) == "Camse"); wassert(actual(Msg::downcast(msgs[0]).get_temp_2m_var()->enqd()) == 273.15); wassert(actual(Msg::downcast(msgs[1]).get_rep_memo_var()->enqc()) == "temp"); wassert(actual(Msg::downcast(msgs[1]).get_st_name_var()->enqc()) == "Esmac"); wassert(actual(Msg::downcast(msgs[1]).get_temp_2m_var()->enqd()) == 274.15); }); add_method("query_ident", [](Fixture& f) { // Try querying by ident auto& db = *f.db; // Insert a mobile station DataValues vals; vals.info.report = "synop"; vals.info.coords = Coords(44.10, 11.50); vals.info.ident = "foo"; vals.info.level = Level(1); vals.info.trange = Trange::instant(); vals.info.datetime = Datetime(2015, 4, 25, 12, 30, 45); vals.values.set("B12101", 295.1); db.insert_data(vals, true, true); wassert(actual(db).try_station_query("ident=foo", 1)); wassert(actual(db).try_station_query("ident=bar", 0)); wassert(actual(db).try_station_query("mobile=1", 1)); wassert(actual(db).try_station_query("mobile=0", 0)); wassert(actual(db).try_data_query("ident=foo", 1)); wassert(actual(db).try_data_query("ident=bar", 0)); wassert(actual(db).try_data_query("mobile=1", 1)); wassert(actual(db).try_data_query("mobile=0", 0)); }); } }; Tests tg1("db_basic_mem", nullptr, db::MEM); Tests tg2("db_basic_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg4("db_basic_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg6("db_basic_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg8("db_basic_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/tests.h0000644000175000017500000002162512652630043012665 00000000000000#include #include #include #include #include namespace dballe { struct DB; namespace db { struct Connection; namespace sql { struct Driver; } namespace v6 { class DB; } } namespace tests { Messages messages_from_db(DB& db, const dballe::Query& query); Messages messages_from_db(DB& db, const char* query); struct OverrideTestDBFormat { dballe::db::Format old_format; OverrideTestDBFormat(dballe::db::Format fmt); ~OverrideTestDBFormat(); }; #if 0 template struct db_tg : public tut::test_group { dballe::db::Format db_format; const char* backend = 0; const char* name; db_tg(const char* name, dballe::db::Format fmt, const char* backend=0) : tut::test_group(name), db_format(fmt), backend(backend), name(name) { } tut::test_result run_next() { dballe::tests::OverrideTestDBFormat otf(db_format); return tut::test_group::run_next(); } tut::test_result run_test(int n) { dballe::tests::OverrideTestDBFormat otf(db_format); return tut::test_group::run_test(n); } }; #endif #if 0 /// Fixture data about a station struct TestStation { double lat; double lon; std::string ident; /// Station information variables for each network std::map info; /// Set our lat, lon and indent into the given record void set_latlonident_into(Record& rec) const; /** * Get a record with all info variables. In case of conflict, keeps only * those with highest priority. * * @param db * Database used to read priority information */ core::Record merged_info_with_highest_prio(DB& db) const; /** * Insert the station and its info in the database. * * Note that if info is empty, nothing will happen, as a station cannot * exist without station vars or measured values. */ void insert(WIBBLE_TEST_LOCPRM, DB& db, bool can_replace=false); }; /// Fixture data about measured variables struct TestRecord { StationValues station; /// Measured variables context, measured variables core::Record data; /// Attributes on measured variables std::map attrs; /// ana_id of this station after inserting it int ana_id; /// Set a value as identified by the Msg ID, with its level, timerange and /// varcode, at the given date and with an optional confidence % void set_var(const char* msgvarname, double val, int conf=-1); void insert(WIBBLE_TEST_LOCPRM, DB& db, bool can_replace=false); }; #endif /// Base for datasets used to populate test databases struct TestDataSet { /// Arbitrarily named station values std::map stations; /// Arbitrarily named data values std::map data; TestDataSet() {} virtual ~TestDataSet() {} virtual void populate_db(DB& db); }; /// Test fixture used by old DB-All.e db tests struct OldDballeTestDataSet : public TestDataSet { OldDballeTestDataSet(); }; std::unique_ptr get_test_connection(const std::string& backend); /// Test fixture for SQL backend drivers struct DriverFixture : public Fixture { std::string backend; db::Format format; db::Connection* conn = nullptr; db::sql::Driver* driver = nullptr; DriverFixture(const char* backend, db::Format format); ~DriverFixture(); void test_setup(); }; #if 0 template struct driver_test_group : public dballe::tests::test_group { const char* backend; db::Format dbformat; driver_test_group(const char* name, const char* backend, db::Format dbformat, const typename dballe::tests::test_group::Tests& tests) : dballe::tests::test_group(name, tests), backend(backend), dbformat(dbformat) { } T* create_fixture() { DriverFixture::backend = backend; DriverFixture::format = dbformat; return dballe::tests::test_group::create_fixture(); } }; #endif struct DBFixture : public Fixture { std::string backend; db::Format format; DB* db = nullptr; DBFixture(const char* backend, db::Format format); ~DBFixture(); /// Open a new DB with the backend and format specified in this fixture std::unique_ptr create_db(); void test_setup(); template void populate() { DataSet data_set; wassert(populate_database(data_set)); } void populate_database(TestDataSet& data_set); }; #if 0 template struct db_test_group : public dballe::tests::test_group { const char* backend; db::Format dbformat; db_test_group(const char* name, const char* backend, db::Format dbformat, const typename dballe::tests::test_group::Tests& tests) : dballe::tests::test_group(name, tests), backend(backend), dbformat(dbformat) { } T* create_fixture() { DBFixture::backend = backend; DBFixture::format = dbformat; return dballe::tests::test_group::create_fixture(); } }; #endif struct ActualCursor : public Actual { using Actual::Actual; /// Check cursor context after a query_stations void station_keys_match(const Station& expected); /// Check cursor context after a query_stations void station_vars_match(const StationValues& expected); /// Check cursor data context after a query_data void data_context_matches(const DataValues& expected); /// Check cursor data variable after a query_data void data_var_matches(const StationValues& expected, wreport::Varcode code) { data_var_matches(*expected.values[code].var); } /// Check cursor data variable after a query_data void data_var_matches(const DataValues& expected, wreport::Varcode code) { data_var_matches(*expected.values[code].var); } /// Check cursor data variable after a query_data void data_var_matches(const DataValues& expected) { if (auto c = dynamic_cast(&_actual)) data_var_matches(*expected.values[c->get_varcode()].var); else throw wreport::error_consistency("cannot call data_var_matches on this kind of cursor"); } /// Check cursor data variable after a query_data void data_var_matches(const Values& expected, wreport::Varcode code) { data_var_matches(*expected[code].var); } /// Check cursor data variable after a query_data void data_var_matches(const wreport::Var& expected); /// Check cursor data context and variable after a query_data void data_matches(const DataValues& ds) { if (auto c = dynamic_cast(&_actual)) data_matches(ds, c->get_varcode()); else throw wreport::error_consistency("cannot call data_matches on this kind of cursor"); } /// Check cursor data context and variable after a query_data void data_matches(const DataValues& ds, wreport::Varcode code); }; typedef std::function&)> result_checker; struct ActualDB : public Actual { using Actual::Actual; /// Check cursor data context anda variable after a query_data void try_data_query(const std::string& query, unsigned expected); /// Check cursor data context anda variable after a query_data void try_data_query(const Query& query, unsigned expected); /// Check results of a station query void try_station_query(const std::string& query, unsigned expected); /// Check results of a summary query void try_summary_query(const std::string& query, unsigned expected, result_checker checker=nullptr); }; inline ActualCursor actual(dballe::db::Cursor& actual) { return ActualCursor(actual); } inline ActualCursor actual(dballe::db::CursorStation& actual) { return ActualCursor(actual); } inline ActualCursor actual(dballe::db::CursorStationData& actual) { return ActualCursor(actual); } inline ActualCursor actual(dballe::db::CursorData& actual) { return ActualCursor(actual); } inline ActualCursor actual(dballe::db::CursorSummary& actual) { return ActualCursor(actual); } inline ActualCursor actual(std::unique_ptr& actual) { return ActualCursor(*actual); } inline ActualCursor actual(std::unique_ptr& actual) { return ActualCursor(*actual); } inline ActualCursor actual(std::unique_ptr& actual) { return ActualCursor(*actual); } inline ActualCursor actual(std::unique_ptr& actual) { return ActualCursor(*actual); } inline ActualCursor actual(std::unique_ptr& actual) { return ActualCursor(*actual); } inline ActualDB actual(dballe::DB& actual) { return ActualDB(actual); } inline ActualDB actual(std::unique_ptr& actual) { return ActualDB(*actual); } } } dballe-7.7/dballe/db/db-query-bench.cc0000644000175000017500000001075112652630043014464 00000000000000#include "dballe/db/bench.h" #include "dballe/core/values.h" #include "dballe/core/query.h" #include "dballe/msg/msg.h" #include "dballe/msg/codec.h" using namespace dballe; using namespace std; using namespace wreport; namespace { struct B : bench::DBBenchmark { benchmark::Task by_latlon; benchmark::Task by_dt; benchmark::Task by_latlon_dt; benchmark::Task by_varcode; std::vector vars; B(const std::string& name) : bench::DBBenchmark::DBBenchmark(name), by_latlon(this, "by_latlon"), by_dt(this, "by_dt"), by_latlon_dt(this, "by_latlon_dt"), by_varcode(this, "by_varcode") { repetitions = 50; vars = { Var(varinfo(WR_VAR(0, 12, 101)), 280.15), Var(varinfo(WR_VAR(0, 12, 103)), 277.15), Var(varinfo(WR_VAR(0, 10, 4)), 1008.0), Var(varinfo(WR_VAR(0, 11, 1)), 42.0), Var(varinfo(WR_VAR(0, 11, 2)), 3.6), }; } void setup_main() { bench::DBBenchmark::setup_main(); /** * Insert the dataset used for query benchmarks */ std::vector reports { "synop", "metar" }; for (int latlon = 0; latlon <= 25; ++latlon) { for (const auto& report: reports) { //fprintf(stderr, "INSERT LATLON %d REPORT %s\n", latlon, report.c_str()); DataValues vals; vals.info.coords = Coords((double)latlon, (double)latlon); vals.info.report = report; for (int year = 2010; year < 2015; ++year) { for (int month = 1; month <= 12; ++month) { vals.info.datetime = Datetime(year, month, 1); for (int levtr = 0; levtr < 5; ++levtr) { vals.info.level = Level(levtr); vals.info.trange = Trange(levtr); vals.values.clear_ids(); for (const auto& var: vars) { vals.values.set(var); } db->insert_data(vals, false, true); } } } } } } void main() override { by_latlon.collect([&]() { for (double latmin = 0; latmin < 25; latmin += 0.4) for (double lonmin = 0; lonmin < 25; lonmin += 0.4) { core::Query query; query.latrange = LatRange(latmin, 25.0); query.lonrange = LonRange(lonmin, 25.0); auto cur = db->query_data(query); while (cur->next()) ; } }); by_dt.collect([&]() { for (double yearmin = 2010; yearmin < 2015; ++yearmin) for (int monthmin = 1; monthmin <= 12; ++monthmin) for (double yearmax = yearmin; yearmax < 2015; ++yearmax) { core::Query query; query.datetime.set( yearmin, monthmin, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, yearmax, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT); auto cur = db->query_data(query); while (cur->next()) ; } }); by_latlon_dt.collect([&]() { for (double latmin = 0; latmin < 25; latmin += 0.4) for (double yearmin = 2010; yearmin < 2015; ++yearmin) { core::Query query; query.latrange = LatRange(latmin, 25.0); query.datetime.set( yearmin, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT); auto cur = db->query_data(query); while (cur->next()) ; } }); by_varcode.collect([&]() { for (const auto& var: vars) { core::Query query; query.varcodes.insert(var.code()); auto cur = db->query_data(query); while (cur->next()) ; } }); } } test("db_query"); } dballe-7.7/dballe/db/db-export-test.cc0000644000175000017500000001332612652630043014541 00000000000000#include "config.h" #include "db/tests.h" #include "db/db.h" #include "dballe/record.h" #include "msg/msg.h" using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct DBData : public TestDataSet { DBData() { data["ds0"].info.coords = Coords(12.34560, 76.54321); data["ds0"].info.report = "synop"; data["ds0"].info.datetime = Datetime(1945, 4, 25, 8, 0); data["ds0"].info.level = Level(1, 2, 0, 3); data["ds0"].info.trange = Trange(4, 5, 6); data["ds0"].values.set("B01012", 500); data["ds1"] = data["ds0"]; data["ds1"].info.datetime = Datetime(1945, 4, 26, 8, 0); data["ds1"].values.set("B01012", 400); data["ds2"].info.coords = Coords(12.34560, 76.54321); data["ds2"].info.report = "synop"; data["ds2"].info.ident = "ciao"; data["ds2"].info.datetime = Datetime(1945, 4, 26, 8, 0); data["ds2"].info.level = Level(1, 2, 0, 3); data["ds2"].info.trange = Trange(4, 5, 6); data["ds2"].values.set("B01012", 300); data["ds3"] = data["ds2"]; data["ds3"].info.report = "metar"; data["ds3"].values.set("B01012", 200); } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("export", [](Fixture& f) { // Simple export auto& db = f.db; wassert(f.populate()); // Put some data in the database and check that it gets exported properly // Query back the data Messages messages = dballe::tests::messages_from_db(*db, core::Query()); wassert(actual(messages.size()) == 4u); int synmsg = 2; int metmsg = 3; if (Msg::downcast(messages[2]).type == MSG_METAR) { // Since the order here is not determined, enforce one std::swap(synmsg, metmsg); } wassert(actual(Msg::downcast(messages[0]).type) == MSG_SYNOP); wassert(actual(messages[0], DBA_MSG_LATITUDE) == 12.34560); wassert(actual(messages[0], DBA_MSG_LONGITUDE) == 76.54321); wassert(actual(messages[0]).is_undef(DBA_MSG_IDENT)); wassert(actual(messages[0].get_datetime()) == Datetime(1945, 4, 25, 8, 0, 0)); wassert(actual(messages[0], WR_VAR(0, 1, 12), Level(1, 2, 0, 3), Trange(4, 5, 6)) == 500); wassert(actual(Msg::downcast(messages[1]).type) == MSG_SYNOP); wassert(actual(messages[1], DBA_MSG_LATITUDE) == 12.34560); wassert(actual(messages[1], DBA_MSG_LONGITUDE) == 76.54321); wassert(actual(messages[1]).is_undef(DBA_MSG_IDENT)); wassert(actual(messages[1].get_datetime()) == Datetime(1945, 4, 26, 8, 0, 0)); wassert(actual(messages[1], WR_VAR(0, 1, 12), Level(1, 2, 0, 3), Trange(4, 5, 6)) == 400); wassert(actual(Msg::downcast(messages[synmsg]).type) == MSG_SYNOP); wassert(actual(messages[synmsg], DBA_MSG_LATITUDE) == 12.34560); wassert(actual(messages[synmsg], DBA_MSG_LONGITUDE) == 76.54321); wassert(actual(messages[synmsg], DBA_MSG_IDENT), "ciao"); wassert(actual(messages[synmsg].get_datetime()) == Datetime(1945, 4, 26, 8, 0, 0)); wassert(actual(messages[synmsg], WR_VAR(0, 1, 12), Level(1, 2, 0, 3), Trange(4, 5, 6)) == 300); wassert(actual(Msg::downcast(messages[metmsg]).type) == MSG_METAR); wassert(actual(messages[metmsg], DBA_MSG_LATITUDE) == 12.34560); wassert(actual(messages[metmsg], DBA_MSG_LONGITUDE) == 76.54321); wassert(actual(messages[metmsg], DBA_MSG_IDENT), "ciao"); wassert(actual(messages[metmsg].get_datetime()) == Datetime(1945, 4, 26, 8, 0, 0)); wassert(actual(messages[metmsg], WR_VAR(0, 1, 12), Level(1, 2, 0, 3), Trange(4, 5, 6)) == 200); }); add_method("export", [](Fixture& f) { // Text exporting of extra station information auto& db = f.db; // Import some data in the station extra information context StationValues st; // do not set datetime, level, trange, to insert a station variable st.info.coords = Coords(45.0, 11.0); st.info.report = "synop"; st.values.set("B01001", 10); db->insert_station_data(st, false, true); // Import one real datum DataValues dv; dv.info = st.info; dv.info.datetime = Datetime(2000, 1, 1, 0, 0, 0); dv.info.level = Level(103, 2000); dv.info.trange = Trange(254, 0, 0); dv.values.set("B12101", 290.0); db->insert_data(dv, false, true); // Query back the data Messages msgs = dballe::tests::messages_from_db(*db, core::Query()); wassert(actual(msgs.size()) == 1u); Msg& msg = Msg::downcast(msgs[0]); wassert(actual(msg.type) == MSG_SYNOP); wassert(actual(msgs[0], DBA_MSG_LATITUDE) == 45.0); wassert(actual(msgs[0], DBA_MSG_LONGITUDE) == 11.0); wassert(actual(msgs[0]).is_undef(DBA_MSG_IDENT)); wassert(actual(msgs[0], DBA_MSG_BLOCK) == 10); wassert(actual(msgs[0], DBA_MSG_TEMP_2M) == 290.0); }); } }; Tests tg1("db_export_mem", nullptr, db::MEM); Tests tg2("db_export_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg4("db_export_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg6("db_export_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg8("db_export_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/db.cc0000644000175000017500000000764712652630043012256 00000000000000#include "config.h" #include "db.h" #include "sql.h" #include "v6/db.h" #include "mem/db.h" #include "sqlite/internals.h" #ifdef HAVE_ODBC #include "odbc/internals.h" #endif #include "dballe/message.h" #include "dballe/core/record.h" #include "dballe/core/values.h" #include #include #include using namespace dballe::db; using namespace std; using namespace wreport; namespace dballe { namespace db { #ifdef HAVE_ODBC static Format default_format = V6; #else static Format default_format = MEM; #endif Cursor::~Cursor() { } unsigned Cursor::test_iterate(FILE* dump) { unsigned count; for (count = 0; next(); ++count) ; return count; } } DB::~DB() { } void DB::import_msgs(const Messages& msgs, const char* repmemo, int flags) { for (const auto& i: msgs) import_msg(i, repmemo, flags); } Format DB::get_default_format() { return default_format; } void DB::set_default_format(Format format) { default_format = format; } bool DB::is_url(const char* str) { if (strncmp(str, "mem:", 4) == 0) return true; if (strncmp(str, "sqlite:", 7) == 0) return true; if (strncmp(str, "postgresql:", 11) == 0) return true; if (strncmp(str, "mysql:", 6) == 0) return true; if (strncmp(str, "odbc://", 7) == 0) return true; if (strncmp(str, "test:", 5) == 0) return true; return false; } unique_ptr DB::create(unique_ptr conn) { // Autodetect format Format format = default_format; bool found = true; // Try with reading it from the settings table string version = conn->get_setting("version"); if (version == "V5") format = V5; else if (version == "V6") format = V6; else if (version == "") found = false;// Some other key exists, but the version has not been set else error_consistency::throwf("unsupported database version: '%s'", version.c_str()); // If it failed, try looking at the existing table structure if (!found) { if (conn->has_table("lev_tr")) format = V6; else if (conn->has_table("context")) format = V5; else format = default_format; } switch (format) { case V5: throw error_unimplemented("V5 format is not supported anymore by this version of DB-All.e"); case V6: return unique_ptr(new v6::DB(unique_ptr(conn.release()))); default: error_consistency::throwf("requested unknown format %d", (int)format); } } unique_ptr DB::connect(const char* dsn, const char* user, const char* password) { #ifdef HAVE_ODBC unique_ptr conn(new ODBCConnection); conn->connect(dsn, user, password); return create(move(conn)); #else throw error_unimplemented("ODBC support is not available"); #endif } unique_ptr DB::connect_from_file(const char* pathname) { unique_ptr conn(new SQLiteConnection); conn->open_file(pathname); return create(unique_ptr(conn.release())); } unique_ptr DB::connect_from_url(const char* url) { if (strncmp(url, "mem:", 4) == 0) { return connect_memory(url + 4); } else { unique_ptr conn(Connection::create_from_url(url)); return create(move(conn)); } } unique_ptr DB::connect_memory(const std::string& arg) { if (arg.empty()) return unique_ptr(new mem::DB()); else return unique_ptr(new mem::DB(arg)); } unique_ptr DB::connect_test() { if (default_format == MEM) return connect_memory(); const char* envurl = getenv("DBA_DB"); if (envurl != NULL) return connect_from_url(envurl); else return connect_from_file("test.sqlite"); } const char* DB::default_repinfo_file() { const char* repinfo_file = getenv("DBA_REPINFO"); if (repinfo_file == 0 || repinfo_file[0] == 0) repinfo_file = TABLE_DIR "/repinfo.csv"; return repinfo_file; } } dballe-7.7/dballe/db/bench.h0000644000175000017500000000251412652630043012576 00000000000000/* * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_BENCH_UTILS_H #define DBALLE_DB_BENCH_UTILS_H #include #include namespace dballe { namespace bench { struct DBBenchmark : wreport::benchmark::Benchmark { using wreport::benchmark::Benchmark::Benchmark; std::unique_ptr db; void setup_main() override { db = DB::connect_test(); db->reset(); } void teardown_main() override { db->disappear(); db.reset(0); } void setup_iteration() { db->remove_all(); } }; } } #endif dballe-7.7/dballe/db/sql.cc0000644000175000017500000000654712652630043012466 00000000000000/* * db/sql - Generic infrastructure for talking with SQL databases * * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "sql.h" #include "config.h" #include "sqlite/internals.h" #ifdef HAVE_ODBC #include "odbc/internals.h" #endif #ifdef HAVE_LIBPQ #include "postgresql/internals.h" #endif #ifdef HAVE_MYSQL #include "mysql/internals.h" #endif #include using namespace std; using namespace wreport; namespace dballe { namespace db { Connection::~Connection() {} void Connection::add_datetime(Querybuf& qb, const Datetime& dt) const { qb.appendf("'%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu'", dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second); } std::unique_ptr Connection::create_from_url(const std::string& url) { return create_from_url(url.c_str()); } std::unique_ptr Connection::create_from_url(const char* url) { if (strncmp(url, "sqlite://", 9) == 0) { unique_ptr conn(new SQLiteConnection); conn->open_file(url + 9); return unique_ptr(conn.release()); } if (strncmp(url, "sqlite:", 7) == 0) { unique_ptr conn(new SQLiteConnection); conn->open_file(url + 7); return unique_ptr(conn.release()); } if (strncmp(url, "mem:", 4) == 0) { throw error_consistency("SQL connections are not available on mem: databases"); } if (strncmp(url, "postgresql:", 11) == 0) { #ifdef HAVE_LIBPQ unique_ptr conn(new PostgreSQLConnection); conn->open_url(url); return unique_ptr(conn.release()); #else throw error_unimplemented("PostgreSQL support is not available"); #endif } if (strncmp(url, "mysql:", 6) == 0) { #ifdef HAVE_MYSQL unique_ptr conn(new MySQLConnection); conn->open_url(url); return unique_ptr(conn.release()); #else throw error_unimplemented("MySQL support is not available"); #endif } if (strncmp(url, "odbc://", 7) == 0) { #ifdef HAVE_ODBC unique_ptr conn(new ODBCConnection); conn->connect_url(url); return unique_ptr(conn.release()); #else throw error_unimplemented("ODBC support is not available"); #endif } if (strncmp(url, "test:", 5) == 0) { const char* envurl = getenv("DBA_DB"); if (envurl != NULL) return create_from_url(envurl); else return create_from_url("sqlite://test.sqlite"); } error_consistency::throwf("unsupported url \"%s\"", url); } } } dballe-7.7/dballe/db/v6/0000755000175000017500000000000012653425050011760 500000000000000dballe-7.7/dballe/db/v6/db.cc0000644000175000017500000002562412652630043012604 00000000000000#include "db.h" #include "dballe/db/sql.h" #include "dballe/db/sql/driver.h" #include "dballe/db/sql/repinfo.h" #include "dballe/db/sql/station.h" #include "dballe/db/sql/levtr.h" #include "dballe/db/sql/datav6.h" #include "dballe/db/sql/attrv6.h" #include "dballe/db/querybuf.h" #include "cursor.h" #include "dballe/core/query.h" #include "dballe/core/record.h" #include "dballe/core/values.h" #include "dballe/types.h" #include #include #include #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace v6 { // First part of initialising a dba_db DB::DB(unique_ptr conn) : conn(conn.release()), m_driver(sql::Driver::create(*this->conn).release()), m_repinfo(0), m_station(0), m_lev_tr(0), m_lev_tr_cache(0), m_data(0), m_attr(0) { init_after_connect(); if (getenv("DBA_EXPLAIN") != NULL) explain_queries = true; auto tr = trace.trace_connect(this->conn->get_url()); /* Set the connection timeout */ /* SQLSetConnectAttr(pc.od_conn, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0); */ tr->done(); } DB::~DB() { delete m_attr; delete m_data; delete m_lev_tr_cache; delete m_lev_tr; delete m_station; delete m_repinfo; delete m_driver; delete conn; } sql::Driver& DB::driver() { return *m_driver; } sql::Repinfo& DB::repinfo() { if (m_repinfo == NULL) m_repinfo = m_driver->create_repinfov6().release(); return *m_repinfo; } sql::Station& DB::station() { if (m_station == NULL) m_station = m_driver->create_stationv6().release(); return *m_station; } sql::LevTr& DB::lev_tr() { if (m_lev_tr == NULL) m_lev_tr = m_driver->create_levtrv6().release(); return *m_lev_tr; } sql::LevTrCache& DB::lev_tr_cache() { if (m_lev_tr_cache == NULL) m_lev_tr_cache = sql::LevTrCache::create(lev_tr()).release(); return *m_lev_tr_cache; } sql::DataV6& DB::data() { if (m_data == NULL) m_data = m_driver->create_datav6().release(); return *m_data; } sql::AttrV6& DB::attr() { if (m_attr == NULL) m_attr = m_driver->create_attrv6().release(); return *m_attr; } void DB::init_after_connect() { } void DB::delete_tables() { m_driver->delete_tables_v6(); } void DB::disappear() { m_driver->delete_tables_v6(); // Invalidate the repinfo cache if we have a repinfo structure active if (m_repinfo) { delete m_repinfo; m_repinfo = 0; } if (m_lev_tr_cache) m_lev_tr_cache->invalidate(); } void DB::reset(const char* repinfo_file) { auto tr = trace.trace_reset(repinfo_file); disappear(); m_driver->create_tables_v6(); // Populate the tables with values int added, deleted, updated; update_repinfo(repinfo_file, &added, &deleted, &updated); tr->done(); } void DB::update_repinfo(const char* repinfo_file, int* added, int* deleted, int* updated) { auto t = conn->transaction(); repinfo().update(repinfo_file, added, deleted, updated); t->commit(); } std::map DB::get_repinfo_priorities() { return repinfo().get_priorities(); } int DB::rep_cod_from_memo(const char* memo) { return repinfo().obtain_id(memo); } int DB::obtain_station(const Station& st, bool can_add) { // Look if the record already knows the ID if (st.ana_id != MISSING_INT) return st.ana_id; sql::Station& s = station(); // Get the ID for the station if (can_add) return s.obtain_id(st.coords.lat, st.coords.lon, st.ident.get()); else return s.get_id(st.coords.lat, st.coords.lon, st.ident.get()); } void DB::insert_station_data(StationValues& vals, bool can_replace, bool station_can_add) { sql::Repinfo& ri = repinfo(); sql::DataV6& d = data(); auto t = conn->transaction(); sql::bulk::InsertV6 vars; // Insert the station data, and get the ID vars.id_station = vals.info.ana_id = obtain_station(vals.info, station_can_add); // Get the ID of the report vars.id_report = ri.obtain_id(vals.info.report.c_str()); // Hardcoded values for station variables vars.datetime = Datetime(1000, 1, 1, 0, 0, 0); // Add all the variables we find for (auto& i: vals.values) vars.add(i.second.var, -1); // Do the insert d.insert(*t, vars, can_replace ? sql::DataV6::UPDATE : sql::DataV6::ERROR); // Read the IDs from the results for (const auto& v: vars) vals.values.add_data_id(v.var->code(), v.id_data); t->commit(); } void DB::insert_data(DataValues& vals, bool can_replace, bool station_can_add) { /* Check for the existance of non-lev_tr data, otherwise it's all * useless. Not inserting data is fine in case of setlev_trana */ if (vals.values.empty()) throw error_notfound("no variables found in input record"); sql::Repinfo& ri = repinfo(); sql::DataV6& d = data(); auto t = conn->transaction(); sql::bulk::InsertV6 vars; // Insert the station data, and get the ID vars.id_station = vals.info.ana_id = obtain_station(vals.info, station_can_add); // Get the ID of the report vars.id_report = ri.obtain_id(vals.info.report.c_str()); // Set the date from the record contents vars.datetime = vals.info.datetime; // Insert the lev_tr data, and get the ID int id_levtr = lev_tr().obtain_id(vals.info.level, vals.info.trange); // Add all the variables we find for (auto& i: vals.values) vars.add(i.second.var, id_levtr); // Do the insert d.insert(*t, vars, can_replace ? sql::DataV6::UPDATE : sql::DataV6::ERROR); // Read the IDs from the results for (const auto& v: vars) vals.values.add_data_id(v.var->code(), v.id_data); t->commit(); } void DB::remove_station_data(const Query& query) { auto tr = trace.trace_remove_station_data(query); auto t = conn->transaction(); cursor::run_delete_query(*this, core::Query::downcast(query), true, explain_queries); t->commit(); tr->done(); } void DB::remove(const Query& query) { auto tr = trace.trace_remove(query); auto t = conn->transaction(); cursor::run_delete_query(*this, core::Query::downcast(query), false, explain_queries); t->commit(); tr->done(); } void DB::remove_all() { auto tr = trace.trace_remove_all(); auto t = conn->transaction(); driver().remove_all_v6(); if (m_lev_tr_cache) m_lev_tr_cache->invalidate(); t->commit(); tr->done(); } void DB::vacuum() { auto tr = trace.trace_vacuum(); auto t = conn->transaction(); driver().vacuum_v6(); if (m_lev_tr_cache) m_lev_tr_cache->invalidate(); t->commit(); tr->done(); } std::unique_ptr DB::query_stations(const Query& query) { auto tr = trace.trace_query_stations(query); auto res = cursor::run_station_query(*this, core::Query::downcast(query), explain_queries); tr->done(); return move(res); } std::unique_ptr DB::query_station_data(const Query& query) { auto tr = trace.trace_query_station_data(query); auto res = cursor::run_station_data_query(*this, core::Query::downcast(query), explain_queries); tr->done(); return move(res); } std::unique_ptr DB::query_data(const Query& query) { auto tr = trace.trace_query_data(query); auto res = cursor::run_data_query(*this, core::Query::downcast(query), explain_queries); tr->done(); return move(res); } std::unique_ptr DB::query_summary(const Query& query) { auto tr = trace.trace_query_summary(query); auto res = cursor::run_summary_query(*this, core::Query::downcast(query), explain_queries); tr->done(); return move(res); } void DB::attr_query_station(int data_id, std::function)>&& dest) { // Create the query sql::AttrV6& a = attr(); a.read(data_id, dest); } void DB::attr_query_data(int data_id, std::function)>&& dest) { // Create the query sql::AttrV6& a = attr(); a.read(data_id, dest); } void DB::attr_insert_station(int data_id, const Values& attrs) { sql::AttrV6& a = attr(); sql::bulk::InsertAttrsV6 iattrs; for (const auto& i : attrs) iattrs.add(i.second.var, data_id); if (iattrs.empty()) return; // Begin the transaction auto t = conn->transaction(); // Insert all the attributes we found a.insert(*t, iattrs, sql::AttrV6::UPDATE); t->commit(); } void DB::attr_insert_data(int data_id, const Values& attrs) { sql::AttrV6& a = attr(); sql::bulk::InsertAttrsV6 iattrs; for (const auto& i : attrs) iattrs.add(i.second.var, data_id); if (iattrs.empty()) return; // Begin the transaction auto t = conn->transaction(); // Insert all the attributes we found a.insert(*t, iattrs, sql::AttrV6::UPDATE); t->commit(); } void DB::attr_remove_station(int data_id, const db::AttrList& qcs) { Querybuf query(500); if (qcs.empty()) // Delete all attributes query.appendf("DELETE FROM attr WHERE id_data=%d", data_id); else { // Delete only the attributes in qcs query.appendf("DELETE FROM attr WHERE id_data=%d AND type IN (", data_id); query.start_list(", "); for (vector::const_iterator i = qcs.begin(); i != qcs.end(); ++i) query.append_listf("%hd", *i); query.append(")"); } driver().exec_no_data(query); // dba_verbose(DBA_VERB_DB_SQL, "Performing query %s for id %d,B%02d%03d\n", query, id_lev_tr, DBA_VAR_X(id_var), DBA_VAR_Y(id_var)); } void DB::attr_remove_data(int data_id, const db::AttrList& qcs) { Querybuf query(500); if (qcs.empty()) // Delete all attributes query.appendf("DELETE FROM attr WHERE id_data=%d", data_id); else { // Delete only the attributes in qcs query.appendf("DELETE FROM attr WHERE id_data=%d AND type IN (", data_id); query.start_list(", "); for (vector::const_iterator i = qcs.begin(); i != qcs.end(); ++i) query.append_listf("%hd", *i); query.append(")"); } driver().exec_no_data(query); // dba_verbose(DBA_VERB_DB_SQL, "Performing query %s for id %d,B%02d%03d\n", query, id_lev_tr, DBA_VAR_X(id_var), DBA_VAR_Y(id_var)); } bool DB::is_station_variable(int data_id, wreport::Varcode varcode) { return false; } void DB::dump(FILE* out) { repinfo().dump(out); station().dump(out); lev_tr().dump(out); lev_tr_cache().dump(out); data().dump(out); attr().dump(out); } #if 0 { /* List DSNs */ char dsn[100], desc[100]; short int len_dsn, len_desc, next; for (next = SQL_FETCH_FIRST; SQLDataSources(pc.od_env, next, dsn, sizeof(dsn), &len_dsn, desc, sizeof(desc), &len_desc) == SQL_SUCCESS; next = SQL_FETCH_NEXT) printf("DSN %s (%s)\n", dsn, desc); } #endif } } } dballe-7.7/dballe/db/v6/export.cc0000644000175000017500000001363112652630043013533 00000000000000#include "db.h" #include "cursor.h" #include "qbuilder.h" #include "dballe/db/sql/driver.h" #include "dballe/db/sql/repinfo.h" #include "dballe/db/sql/station.h" #include "dballe/db/sql/levtr.h" #include "dballe/db/sql/attrv6.h" #include "dballe/msg/msg.h" #include "dballe/msg/context.h" #include "dballe/core/query.h" #include "dballe/core/structbuf.h" #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace v6 { namespace { struct StationLayerCache : protected std::vector { ~StationLayerCache() { for (iterator i = begin(); i != end(); ++i) delete *i; } void reset() { for (iterator i = begin(); i != end(); ++i) delete *i; clear(); } void to_context(msg::Context& c) const { for (const_iterator i = begin(); i != end(); ++i) c.set(**i); } void fill(DB& db, int id_station, int id_report) { reset(); db.station().get_station_vars(id_station, id_report, [&](std::unique_ptr var) { push_back(var.release()); }); } }; } bool DB::export_msgs(const dballe::Query& query, std::function&&)> dest) { auto tr = trace.trace_export_msgs(query); sql::Repinfo& ri = repinfo(); sql::AttrV6& at = attr(); sql::LevTrCache& ltrc = lev_tr_cache(); // Message being built unique_ptr msg; auto t = conn->transaction(); // The big export query DataQueryBuilder qb(*this, core::Query::downcast(query), DBA_DB_MODIFIER_SORT_FOR_EXPORT, false); qb.build(); // Current context information used to detect context changes Datetime last_datetime; int last_ana_id = -1; int last_rep_cod = -1; StationLayerCache station_cache; // Retrieve results, buffering them locally to avoid performing concurrent // queries Structbuf results; driver().run_built_query_v6(qb, [&](sql::SQLRecordV6& sqlrec) { results.append(sqlrec); }); results.ready_to_read(); for (unsigned row = 0; row < results.size(); ++row) { const sql::SQLRecordV6& sqlrec = results[row]; //TRACE("Got B%02d%03d %ld,%ld, %ld,%ld %ld,%ld,%ld %s\n", // WR_VAR_X(sqlrec.out_varcode), WR_VAR_Y(sqlrec.out_varcode), // sqlrec.out_ltype1, sqlrec.out_l1, sqlrec.out_ltype2, sqlrec.out_l2, sqlrec.out_pind, sqlrec.out_p1, sqlrec.out_p2, // sqlrec.out_value); /* Create the variable that we got on this iteration */ unique_ptr var(newvar(sqlrec.out_varcode, sqlrec.out_value)); /* Load the attributes from the database */ at.read(sqlrec.out_id_data, [&](unique_ptr attr) { var->seta(auto_ptr(attr.release())); }); /* See if we have the start of a new message */ if (sqlrec.out_ana_id != last_ana_id || sqlrec.out_rep_cod != last_rep_cod || sqlrec.out_datetime != last_datetime) { // Flush current message TRACE("New message\n"); if (msg.get() != NULL) { TRACE("Sending old message to consumer\n"); if (msg->type == MSG_PILOT || msg->type == MSG_TEMP || msg->type == MSG_TEMP_SHIP) { unique_ptr copy(new Msg); msg->sounding_pack_levels(*copy); /* DBA_RUN_OR_GOTO(cleanup, dba_msg_sounding_reverse_levels(msg)); */ if (!dest(move(copy))) return false; } else if (!dest(move(msg))) return false; } // Start writing a new message msg.reset(new Msg); // Fill in datetime msg->set_datetime(sqlrec.out_datetime); msg::Context& c_st = msg->obtain_station_context(); // Update station layer cache if needed if (sqlrec.out_ana_id != last_ana_id || sqlrec.out_rep_cod != last_rep_cod) station_cache.fill(*this, sqlrec.out_ana_id, sqlrec.out_rep_cod); // Fill in report information { const char* memo = ri.get_rep_memo(sqlrec.out_rep_cod); c_st.set_rep_memo(memo); msg->type = Msg::type_from_repmemo(memo); } // Fill in the basic station values c_st.seti(WR_VAR(0, 5, 1), sqlrec.out_lat); c_st.seti(WR_VAR(0, 6, 1), sqlrec.out_lon); if (sqlrec.out_ident_size != -1) c_st.set_ident(sqlrec.out_ident); // Fill in station information station_cache.to_context(c_st); // Update current context information last_datetime = sqlrec.out_datetime; last_ana_id = sqlrec.out_ana_id; last_rep_cod = sqlrec.out_rep_cod; } TRACE("Inserting var B%02d%03d (%s)\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code()), var->value()); if (sqlrec.out_id_ltr == -1) { msg->set(move(var), Level(), Trange()); } else { msg::Context* ctx = ltrc.to_msg(sqlrec.out_id_ltr, *msg); if (ctx) ctx->set(move(var)); } } if (msg.get() != NULL) { TRACE("Inserting leftover old message\n"); if (msg->type == MSG_PILOT || msg->type == MSG_TEMP || msg->type == MSG_TEMP_SHIP) { unique_ptr copy(new Msg); msg->sounding_pack_levels(*copy); /* DBA_RUN_OR_GOTO(cleanup, dba_msg_sounding_reverse_levels(msg)); */ if (!dest(move(copy))) return false; msg.release(); } else if (!dest(move(msg))) return false; } // Useful for Oracle to end the session t->commit(); tr->done(); return true; } } } } dballe-7.7/dballe/db/v6/qbuilder.h0000644000175000017500000000617512652630043013670 00000000000000#ifndef DBA_DB_V6_QBUILDER_H #define DBA_DB_V6_QBUILDER_H #include #include #include #include #include namespace dballe { namespace db { namespace v6 { /// Build SQL queries for V6 databases struct QueryBuilder { Connection& conn; /** Database to operate on */ DB& db; /** * If defined, it need to point to the identifier to be used as the only * bound input parameter. * * If not defined, there are no bound input parameters in this query */ const char* bind_in_ident = nullptr; bool select_station = false; // ana_id, lat, lon, ident bool select_varinfo = false; // rep_cod, id_ltr, varcode // IdQuery bool select_data_id = false; // id_data // DataQuery bool select_data = false; // datetime, value // SummaryQuery bool select_summary_details = false; // id_data, datetime, datetimemax /// Query object const core::Query& query; /** Dynamically generated SQL query */ Querybuf sql_query; /// FROM part of the SQL query Querybuf sql_from; /// WHERE part of the SQL query Querybuf sql_where; /// Modifier flags to enable special query behaviours const unsigned int modifiers; /// True if we are querying station information, rather than measured data bool query_station_vars; QueryBuilder(DB& db, const core::Query& query, unsigned int modifiers, bool query_station_vars); virtual ~QueryBuilder() {} void build(); protected: // Add WHERE conditions bool add_pa_where(const char* tbl); bool add_dt_where(const char* tbl); bool add_ltr_where(const char* tbl); bool add_varcode_where(const char* tbl); bool add_repinfo_where(const char* tbl); bool add_datafilter_where(const char* tbl); bool add_attrfilter_where(const char* tbl); virtual void build_select() = 0; virtual bool build_where() = 0; virtual void build_order_by() = 0; }; struct StationQueryBuilder : public QueryBuilder { StationQueryBuilder(DB& db, const core::Query& query, unsigned int modifiers) : QueryBuilder(db, query, modifiers, false) {} virtual void build_select(); virtual bool build_where(); virtual void build_order_by(); }; struct DataQueryBuilder : public QueryBuilder { DataQueryBuilder(DB& db, const core::Query& query, unsigned int modifiers, bool query_station_vars); virtual void build_select(); virtual bool build_where(); virtual void build_order_by(); }; struct IdQueryBuilder : public DataQueryBuilder { IdQueryBuilder(DB& db, const core::Query& query, unsigned int modifiers, bool query_station_vars) : DataQueryBuilder(db, query, modifiers, query_station_vars) {} virtual void build_select(); virtual void build_order_by(); }; struct SummaryQueryBuilder : public DataQueryBuilder { SummaryQueryBuilder(DB& db, const core::Query& query, unsigned int modifiers, bool query_station_vars) : DataQueryBuilder(db, query, modifiers, query_station_vars) {} virtual void build_select(); virtual void build_order_by(); }; } } } #endif dballe-7.7/dballe/db/v6/qbuilder.cc0000644000175000017500000005441412652630043014025 00000000000000#include "qbuilder.h" #include "dballe/core/defs.h" #include "dballe/core/aliases.h" #include "dballe/core/query.h" #include "dballe/var.h" #include "dballe/db/sql/repinfo.h" #include #include #include #include #include "config.h" #ifdef HAVE_LIBPQ #include "dballe/db/postgresql/internals.h" #endif #ifdef HAVE_MYSQL #include "dballe/db/mysql/internals.h" #endif using namespace std; using namespace wreport; namespace dballe { namespace db { namespace v6 { static Varcode parse_varcode(const char* str, regmatch_t pos) { Varcode res; /* Parse the varcode */ if (str[pos.rm_so] == 'B') res = WR_STRING_TO_VAR(str + pos.rm_so + 1); else res = varcode_alias_resolve_substring(str + pos.rm_so, pos.rm_eo - pos.rm_so); if (res == 0) error_consistency::throwf("cannot resolve the variable code or alias in \"%.*s\"", pos.rm_eo - pos.rm_so, str + pos.rm_so); return res; } static void parse_value(const char* str, regmatch_t pos, Varinfo info, char* value) { /* Parse the value */ const char* s = str + pos.rm_so; int len = pos.rm_eo - pos.rm_so; switch (info->type) { case Vartype::String: { // Copy the string, escaping quotes int i = 0, j = 0; value[j++] = '\''; for (; i < len && j < 253; ++i, ++j) { if (s[i] == '\'') value[j++] = '\\'; value[j] = s[i]; } value[j++] = '\''; value[j] = 0; break; } case Vartype::Binary: throw error_consistency("cannot use a *_filter on a binary variable"); case Vartype::Integer: case Vartype::Decimal: { double dval; if (sscanf(s, "%lf", &dval) != 1) error_consistency::throwf("value in \"%.*s\" must be a number", len, s); sprintf(value, "%d", info->encode_decimal(dval)); break; } } } static Varinfo decode_data_filter(const std::string& filter, const char** op, const char** val, const char** val1) { static regex_t* re_normal = NULL; static regex_t* re_between = NULL; regmatch_t matches[4]; static char oper[5]; static char value[255]; static char value1[255]; #if 0 size_t len = strcspn(filter, "<=>"); const char* s = filter + len; #endif Varcode code; /* Compile the regular expression if it has not yet been done */ if (re_normal == NULL) { re_normal = new regex_t; if (int res = regcomp(re_normal, "^([^<=>]+)([<=>]+)([^<=>]+)$", REG_EXTENDED)) throw error_regexp(res, re_normal, "compiling regular expression to match normal filters"); } if (re_between == NULL) { re_between = new regex_t; if (int res = regcomp(re_between, "^([^<=>]+)<=([^<=>]+)<=([^<=>]+)$", REG_EXTENDED)) throw error_regexp(res, re_between, "compiling regular expression to match 'between' filters"); } int res = regexec(re_normal, filter.c_str(), 4, matches, 0); if (res != 0 && res != REG_NOMATCH) error_regexp::throwf(res, re_normal, "Trying to parse '%s' as a 'normal' filter", filter.c_str()); if (res == 0) { int len; /* We have a normal filter */ /* Parse the varcode */ code = parse_varcode(filter.c_str(), matches[1]); /* Query informations for the varcode */ Varinfo info = varinfo(code); /* Parse the operator */ len = matches[2].rm_eo - matches[2].rm_so; if (len > 4) error_consistency::throwf("operator %.*s is not valid", len, filter.c_str() + matches[2].rm_so); memcpy(oper, filter.c_str() + matches[2].rm_so, len); oper[len] = 0; if (strcmp(oper, "!=") == 0) *op = "<>"; else if (strcmp(oper, "==") == 0) *op = "="; else *op = oper; /* Parse the value */ parse_value(filter.c_str(), matches[3], info, value); *val = value; *val1 = NULL; return info; } else { res = regexec(re_between, filter.c_str(), 4, matches, 0); if (res == REG_NOMATCH) error_consistency::throwf("%s is not a valid filter", filter.c_str()); if (res != 0) error_regexp::throwf(res, re_normal, "Trying to parse '%s' as a 'between' filter", filter.c_str()); /* We have a between filter */ /* Parse the varcode */ code = parse_varcode(filter.c_str(), matches[2]); /* Query informations for the varcode */ Varinfo info = varinfo(code); /* No need to parse the operator */ oper[0] = 0; *op = oper; /* Parse the values */ parse_value(filter.c_str(), matches[1], info, value); parse_value(filter.c_str(), matches[3], info, value1); *val = value; *val1 = value1; return info; } } struct Constraints { const core::Query& query; const char* tbl; Querybuf& q; bool found; Constraints(const core::Query& query, const char* tbl, Querybuf& q) : query(query), tbl(tbl), q(q), found(false) {} #if 0 void add_int(dba_keyword key, const char* sql) { const Var* var = rec.key_peek(key); if (!var || !var->isset()) return; //TRACE("found %s: adding %s. val is %d\n", info(key)->desc, sql, *out); q.append_listf(sql, tbl, var->enqi()); found = true; } #endif void add_lat() { if (query.latrange.is_missing()) return; if (query.latrange.imin == query.latrange.imax) q.append_listf("%s.lat=%d", tbl, query.latrange.imin); else { if (query.latrange.imin != LatRange::IMIN) q.append_listf("%s.lat>=%d", tbl, query.latrange.imin); if (query.latrange.imax != LatRange::IMAX) q.append_listf("%s.lat<=%d", tbl, query.latrange.imax); } found = true; } void add_lon() { if (query.lonrange.is_missing()) return; if (query.lonrange.imin == query.lonrange.imax) q.append_listf("%s.lon=%d", tbl, query.lonrange.imin); else if (query.lonrange.imin < query.lonrange.imax) q.append_listf("%s.lon>=%d AND %s.lon<=%d", tbl, query.lonrange.imin, tbl, query.lonrange.imax); else q.append_listf("((%s.lon>=%d AND %s.lon<=18000000) OR (%s.lon>=-18000000 AND %s.lon<=%d))", tbl, query.lonrange.imin, tbl, tbl, tbl, query.lonrange.imax); found = true; } void add_mobile() { if (query.mobile != MISSING_INT) { if (query.mobile == 0) { q.append_listf("%s.ident IS NULL", tbl); TRACE("found fixed/mobile: adding AND %s.ident IS NULL.\n", tbl); } else { q.append_listf("NOT (%s.ident IS NULL)", tbl); TRACE("found fixed/mobile: adding AND NOT (%s.ident IS NULL)\n", tbl); } found = true; } } }; QueryBuilder::QueryBuilder(DB& db, const core::Query& query, unsigned int modifiers, bool query_station_vars) : conn(*db.conn), db(db), query(query), sql_query(2048), sql_from(1024), sql_where(1024), modifiers(modifiers), query_station_vars(query_station_vars) { } DataQueryBuilder::DataQueryBuilder(DB& db, const core::Query& query, unsigned int modifiers, bool query_station_vars) : QueryBuilder(db, query, modifiers, query_station_vars) { } void QueryBuilder::build() { build_select(); sql_where.start_list(" AND "); bool has_where = build_where(); if (query.limit != MISSING_INT && conn.server_type == ServerType::ORACLE) { sql_where.append_listf("rownum <= %d", query.limit); has_where = true; } // Finalise the query sql_query.append(sql_from); if (has_where) { sql_query.append(" WHERE "); sql_query.append(sql_where); } // Append ORDER BY as needed if (!(modifiers & DBA_DB_MODIFIER_UNSORTED)) { if (query.limit != MISSING_INT && conn.server_type == ServerType::ORACLE) throw error_unimplemented("sorted queries with result limit are not implemented for Oracle"); build_order_by(); } // Append LIMIT if requested if (query.limit != MISSING_INT && conn.server_type != ServerType::ORACLE) sql_query.appendf(" LIMIT %d", query.limit); } void StationQueryBuilder::build_select() { sql_query.append("SELECT s.id, s.lat, s.lon, s.ident"); sql_from.append( " FROM station s" ); select_station = true; } bool StationQueryBuilder::build_where() { bool has_where = false; // Add pseudoana-specific where parts has_where |= add_pa_where("s"); switch (query.varcodes.size()) { case 0: break; case 1: sql_where.append_listf("EXISTS(SELECT id FROM data s_stvar" " WHERE s_stvar.id_station=s.id AND s_stvar.id_lev_tr != -1" " AND s_stvar.id_var=%d)", *query.varcodes.begin()); has_where = true; break; default: sql_where.append_listf("EXISTS(SELECT id FROM data s_stvar" " WHERE s_stvar.id_station=s.id AND s_stvar.id_lev_tr != -1" " AND s_stvar.id_var IN ("); sql_where.append_varlist(query.varcodes); sql_where.append("))"); has_where = true; break; } return has_where; } void StationQueryBuilder::build_order_by() { sql_query.append(" ORDER BY s.id"); } void DataQueryBuilder::build_select() { sql_query.append("SELECT s.id, s.lat, s.lon, s.ident, d.id_report, d.id_lev_tr, d.id_var, d.id, d.datetime, d.value"); select_station = true; select_varinfo = true; select_data_id = true; select_data = true; sql_from.append( " FROM station s" " JOIN data d ON s.id=d.id_station" ); if (!query_station_vars) sql_from.append(" JOIN lev_tr ltr ON ltr.id=d.id_lev_tr"); } bool DataQueryBuilder::build_where() { if (query_station_vars) sql_where.append_list("d.id_lev_tr = -1"); else sql_where.append_list("d.id_lev_tr != -1"); // Add pseudoana-specific where parts add_pa_where("s"); add_dt_where("d"); add_ltr_where("ltr"); add_varcode_where("d"); add_repinfo_where("d"); add_datafilter_where("d"); add_attrfilter_where("d"); return true; } void DataQueryBuilder::build_order_by() { sql_query.append(" ORDER BY d.id_station"); if (modifiers & DBA_DB_MODIFIER_SORT_FOR_EXPORT) sql_query.append(", d.id_report"); sql_query.append(", d.datetime"); if (!query_station_vars) sql_query.append(", ltr.ltype1, ltr.l1, ltr.ltype2, ltr.l2, ltr.ptype, ltr.p1, ltr.p2"); // TODO: id_report should be at the end, so we get all the variables for a // given report. If this has not been caught so far, are clients actually // relying on ordering? If not, negotiate relaxing of ordering requirements (#19) if (!(modifiers & DBA_DB_MODIFIER_SORT_FOR_EXPORT)) sql_query.append(", d.id_report"); sql_query.append(", d.id_var"); } void IdQueryBuilder::build_select() { sql_query.append("SELECT d.id"); select_data_id = true; sql_from.append( " FROM station s" " JOIN data d ON s.id = d.id_station" ); if (!query_station_vars) sql_from.append(" JOIN lev_tr ltr ON ltr.id = d.id_lev_tr"); } void IdQueryBuilder::build_order_by() { // No ordering required } void SummaryQueryBuilder::build_select() { if (modifiers & DBA_DB_MODIFIER_SUMMARY_DETAILS) { sql_query.append(R"( SELECT s.id, s.lat, s.lon, s.ident, d.id_report, d.id_lev_tr, d.id_var, COUNT(1), MIN(d.datetime), MAX(d.datetime) )"); select_summary_details = true; } else { sql_query.append("SELECT DISTINCT s.id, s.lat, s.lon, s.ident, d.id_report, d.id_lev_tr, d.id_var"); } select_station = true; select_varinfo = true; /* // Abuse id_data and datetime for count and min(datetime) stm.bind_out(output_seq++, cur.sqlrec.out_id_data); stm.bind_out(output_seq++, cur.sqlrec.out_datetime); stm.bind_out(output_seq++, cur_s.out_datetime_max); */ sql_from.append( " FROM station s" " JOIN data d ON s.id = d.id_station" ); if (!query_station_vars) sql_from.append(" JOIN lev_tr ltr ON ltr.id=d.id_lev_tr"); } void SummaryQueryBuilder::build_order_by() { // No ordering required, but we may add a GROUP BY if (modifiers & DBA_DB_MODIFIER_SUMMARY_DETAILS) sql_query.append(" GROUP BY s.id, d.id_report, d.id_lev_tr, d.id_var"); } bool QueryBuilder::add_pa_where(const char* tbl) { Constraints c(query, tbl, sql_where); if (query.ana_id != MISSING_INT) { sql_where.append_listf("%s.id=%d", tbl, query.ana_id); c.found = true; } c.add_lat(); c.add_lon(); c.add_mobile(); if (!query.ident.is_missing()) { if (false) { // This is only here to move the other optional bits into else ifs // that can be compiled out ; #if HAVE_LIBPQ } else if (PostgreSQLConnection* c = dynamic_cast(&conn)) { sql_where.append_listf("%s.ident=$1::text", tbl); bind_in_ident = query.ident.get(); TRACE("found ident: adding AND %s.ident=$1::text. val is %s\n", tbl, query.ident.get()); #endif #if HAVE_MYSQL } else if (MySQLConnection* c = dynamic_cast(&conn)) { string escaped = c->escape(query.ident.get()); sql_where.append_listf("%s.ident='%s'", tbl, escaped.c_str()); TRACE("found ident: adding AND %s.ident='%s'. val is %s\n", tbl, escape.c_str(), query.ident.get()); #endif } else { sql_where.append_listf("%s.ident=?", tbl); bind_in_ident = query.ident.get(); TRACE("found ident: adding AND %s.ident = ?. val is %s\n", tbl, query.ident.get()); } c.found = true; } if (query.block != MISSING_INT) { // No need to escape since the variable is integer sql_where.append_listf("EXISTS(SELECT id FROM data %s_blo WHERE %s_blo.id_station=%s.id" " AND %s_blo.id_var=257 AND %s_blo.id_lev_tr = -1 AND %s_blo.value='%d')", tbl, tbl, tbl, tbl, tbl, tbl, query.block); c.found = true; } if (query.station != MISSING_INT) { sql_where.append_listf("EXISTS(SELECT id FROM data %s_sta WHERE %s_sta.id_station=%s.id" " AND %s_sta.id_var=258 AND %s_sta.id_lev_tr = -1 AND %s_sta.value='%d')", tbl, tbl, tbl, tbl, tbl, tbl, query.station); c.found = true; } if (!query.ana_filter.empty()) { const char *op, *value, *value1; Varinfo info = decode_data_filter(query.ana_filter, &op, &value, &value1); sql_where.append_listf("EXISTS(SELECT id FROM data %s_af WHERE %s_af.id_station=%s.id" " AND %s_af.id_lev_tr = -1" " AND %s_af.id_var=%d", tbl, tbl, tbl, tbl, tbl, info->code); if (value[0] == '\'') if (value1 == NULL) sql_where.appendf(" AND %s_af.value%s%s)", tbl, op, value); else sql_where.appendf(" AND %s_af.value BETWEEN %s AND %s)", tbl, value, value1); else { const char* type = (conn.server_type == ServerType::MYSQL) ? "SIGNED" : "INT"; if (value1 == NULL) sql_where.appendf(" AND CAST(%s_af.value AS %s)%s%s)", tbl, type, op, value); else sql_where.appendf(" AND CAST(%s_af.value AS %s) BETWEEN %s AND %s)", tbl, type, value, value1); } c.found = true; } return c.found; } bool QueryBuilder::add_dt_where(const char* tbl) { if (query_station_vars) return false; bool found = false; if (!query.datetime.is_missing()) { Datetime dtmin = query.datetime.min; Datetime dtmax = query.datetime.max; if (dtmin == dtmax) { // Add constraint on the exact date interval sql_where.append_listf("%s.datetime=", tbl); conn.add_datetime(sql_where, dtmin); TRACE("found exact time: adding AND %s.datetime={ts '%04d-%02d-%02d %02d:%02d:%02d.000'}\n", tbl, minvalues[0], minvalues[1], minvalues[2], minvalues[3], minvalues[4], minvalues[5]); found = true; } else { if (!dtmin.is_missing()) { // Add constraint on the minimum date interval sql_where.append_listf("%s.datetime>=", tbl); conn.add_datetime(sql_where, dtmin); TRACE("found min time: adding AND %s.datetime>={ts '%04d-%02d-%02d %02d:%02d:%02d.000'}\n", tbl, minvalues[0], minvalues[1], minvalues[2], minvalues[3], minvalues[4], minvalues[5]); found = true; } if (!dtmax.is_missing()) { sql_where.append_listf("%s.datetime<=", tbl); conn.add_datetime(sql_where, dtmax); TRACE("found max time: adding AND %s.datetime<={ts '%04d-%02d-%02d %02d:%02d:%02d.000'}\n", tbl, maxvalues[0], maxvalues[1], maxvalues[2], maxvalues[3], maxvalues[4], maxvalues[5]); found = true; } } } return found; } bool QueryBuilder::add_ltr_where(const char* tbl) { if (query_station_vars) return false; bool found = false; if (query.level.ltype1 != MISSING_INT) { sql_where.append_listf("%s.ltype1=%d", tbl, query.level.ltype1); found = true; } if (query.level.l1 != MISSING_INT) { sql_where.append_listf("%s.l1=%d", tbl, query.level.l1); found = true; } if (query.level.ltype2 != MISSING_INT) { sql_where.append_listf("%s.ltype2=%d", tbl, query.level.ltype2); found = true; } if (query.level.l2 != MISSING_INT) { sql_where.append_listf("%s.l2=%d", tbl, query.level.l2); found = true; } if (query.trange.pind != MISSING_INT) { sql_where.append_listf("%s.ptype=%d", tbl, query.trange.pind); found = true; } if (query.trange.p1 != MISSING_INT) { sql_where.append_listf("%s.p1=%d", tbl, query.trange.p1); found = true; } if (query.trange.p2 != MISSING_INT) { sql_where.append_listf("%s.p2=%d", tbl, query.trange.p2); found = true; } return found; } bool QueryBuilder::add_varcode_where(const char* tbl) { bool found = false; switch (query.varcodes.size()) { case 0: break; case 1: sql_where.append_listf("%s.id_var=%d", tbl, (int)*query.varcodes.begin()); TRACE("found b: adding AND %s.id_var=%d\n", tbl, (int)*query.varcodes.begin()); found = true; break; case 2: sql_where.append_listf("%s.id_var IN (", tbl); sql_where.append_varlist(query.varcodes); sql_where.append(")"); TRACE("found blist: adding AND %s.id_var IN (%s)\n", tbl, val); found = true; break; } return found; } bool QueryBuilder::add_repinfo_where(const char* tbl) { bool found = false; if (query.prio_min != MISSING_INT || query.prio_max != MISSING_INT) { // Filter the repinfo cache and build a IN query std::vector ids = db.repinfo().ids_by_prio(query); if (ids.empty()) { // No repinfo matches, so we just introduce a false value sql_where.append_list("1=0"); } else { sql_where.append_listf("%s.id_report IN (", tbl); for (std::vector::const_iterator i = ids.begin(); i != ids.end(); ++i) { if (i == ids.begin()) sql_where.appendf("%d", *i); else sql_where.appendf(",%d", *i); } sql_where.append(")"); } found = true; } if (!query.rep_memo.empty()) { int src_val = db.repinfo().get_id(query.rep_memo.c_str()); sql_where.append_listf("%s.id_report=%d", tbl, src_val); TRACE("found rep_memo %s: adding AND %s.id_report=%d\n", val, tbl, (int)src_val); found = true; } return found; } bool QueryBuilder::add_datafilter_where(const char* tbl) { if (query.data_filter.empty()) return false; const char *op, *value, *value1; Varinfo info = decode_data_filter(query.data_filter, &op, &value, &value1); sql_where.append_listf("%s.id_var=%d", tbl, (int)info->code); if (value[0] == '\'') if (value1 == NULL) sql_where.append_listf("%s.value%s%s", tbl, op, value); else sql_where.append_listf("%s.value BETWEEN %s AND %s", tbl, value, value1); else { const char* type = (conn.server_type == ServerType::MYSQL) ? "SIGNED" : "INT"; if (value1 == NULL) sql_where.append_listf("CAST(%s.value AS %s)%s%s", tbl, type, op, value); else sql_where.append_listf("CAST(%s.value AS %s) BETWEEN %s AND %s", tbl, type, value, value1); } return true; } bool QueryBuilder::add_attrfilter_where(const char* tbl) { if (query.attr_filter.empty()) return false; const char *op, *value, *value1; Varinfo info = decode_data_filter(query.attr_filter, &op, &value, &value1); sql_from.appendf(" JOIN attr %s_atf ON %s.id=%s_atf.id_data AND %s_atf.type=%d", tbl, tbl, tbl, tbl, info->code); if (value[0] == '\'') if (value1 == NULL) sql_where.append_listf("%s_atf.value%s%s", tbl, op, value); else sql_where.append_listf("%s_atf.value BETWEEN %s AND %s", tbl, value, value1); else { const char* type = (conn.server_type == ServerType::MYSQL) ? "SIGNED" : "INT"; if (value1 == NULL) sql_where.append_listf("CAST(%s_atf.value AS %s)%s%s", tbl, type, op, value); else sql_where.append_listf("CAST(%s_atf.value AS %s) BETWEEN %s AND %s", tbl, type, value, value1); } return true; } } } } dballe-7.7/dballe/db/v6/cursor.cc0000644000175000017500000004175212652630043013534 00000000000000#include "cursor.h" #include "qbuilder.h" #include "db.h" #include #include "dballe/db/sql/repinfo.h" #include "dballe/db/sql/station.h" #include "dballe/db/sql/levtr.h" #include "dballe/db/sql/datav6.h" #include "dballe/types.h" #include "dballe/record.h" #include "dballe/var.h" #include "dballe/core/query.h" #include "dballe/core/structbuf.h" #include "wreport/var.h" #include #include namespace { // Consts used for to_record_todo const unsigned int TOREC_PSEUDOANA = 1 << 0; const unsigned int TOREC_BASECONTEXT = 1 << 1; const unsigned int TOREC_DATACONTEXT = 1 << 2; const unsigned int TOREC_DATA = 1 << 3; } using namespace std; using namespace wreport; namespace dballe { namespace db { namespace v6 { namespace cursor { namespace { /** * Simple typedef to make typing easier, and also to help some versions of swig * match this complex type */ typedef std::vector AttrList; /** * Structure used to build and execute a query, and to iterate through the * results */ template struct Base : public Interface { /// Database to operate on v6::DB& db; /** Modifier flags to enable special query behaviours */ const unsigned int modifiers; /// Results from the query Structbuf results; /// Current result element being iterated int cur = -1; Base(v6::DB& db, unsigned int modifiers) : db(db), modifiers(modifiers) { } virtual ~Base() {} dballe::DB& get_db() const override { return db; } /** * Get the number of rows still to be fetched * * @return * The number of rows still to be queried. The value is undefined if no * query has been successfully peformed yet using this cursor. */ int remaining() const override { if (cur == -1) return results.size(); return results.size() - cur - 1; } bool next() override { ++cur; return (size_t)cur < results.size(); } void discard_rest() override { cur = results.size(); } #if 0 /** * Query attributes for the current variable */ void query_attrs(std::function&&)> dest) override; void attr_insert(const Values& attrs) override; void attr_remove(const AttrList& qcs) override; #endif int get_station_id() const override { return results[cur].out_ana_id; } double get_lat() const override { return (double)results[cur].out_lat / 100000.0; } double get_lon() const override { return (double)results[cur].out_lon / 100000.0; } const char* get_ident(const char* def=0) const override { if (results[cur].out_ident_size == -1 || results[cur].out_ident[0] == 0) return def; return results[cur].out_ident; } const char* get_rep_memo() const override { return db.repinfo().get_rep_memo(results[cur].out_rep_cod); } /** * Iterate the cursor until the end, returning the number of items. * * If dump is a FILE pointer, also dump the cursor values to it */ unsigned test_iterate(FILE* dump=0) override = 0; /// Run the query in qb and fill results with its output virtual void load(const QueryBuilder& qb) { db.driver().run_built_query_v6(qb, [&](sql::SQLRecordV6& rec) { results.append(rec); }); // We are done adding, prepare the structbuf for reading results.ready_to_read(); } void to_record_pseudoana(Record& rec) { rec.seti("ana_id", results[cur].out_ana_id); rec.seti("lat", results[cur].out_lat); rec.seti("lon", results[cur].out_lon); if (results[cur].out_ident_size != -1 && results[cur].out_ident[0] != 0) { rec.setc("ident", results[cur].out_ident); rec.seti("mobile", 1); } else { rec.unset("ident"); rec.seti("mobile", 0); } } void to_record_repinfo(Record& rec) { db.repinfo().to_record(results[cur].out_rep_cod, rec); } void to_record_ltr(Record& rec) { if (results[cur].out_id_ltr != -1) db.lev_tr_cache().to_rec(results[cur].out_id_ltr, rec); else { rec.unset("leveltype1"); rec.unset("l1"); rec.unset("leveltype2"); rec.unset("l2"); rec.unset("pindicator"); rec.unset("p1"); rec.unset("p2"); } } void to_record_datetime(Record& rec) { rec.set(results[cur].out_datetime); } void to_record_varcode(Record& rec) { char bname[7]; snprintf(bname, 7, "B%02d%03d", WR_VAR_X(results[cur].out_varcode), WR_VAR_Y(results[cur].out_varcode)); rec.setc("var", bname); } /// Query extra station info and add it to \a rec void add_station_info(Record& rec) { db.station().add_station_vars(results[cur].out_ana_id, rec); } }; struct Stations : public Base { Stations(DB& db, unsigned int modifiers) : Base(db, modifiers) {} ~Stations() {} void to_record(Record& rec) override { to_record_pseudoana(rec); add_station_info(rec); } unsigned test_iterate(FILE* dump=0) override { auto r = Record::create(); unsigned count; for (count = 0; next(); ++count) { if (dump) { to_record(*r); fprintf(dump, "%02d %02.4f %02.4f %-10s\n", r->enq("ana_id", -1), r->enq("lat", 0.0), r->enq("lon", 0.0), r->enq("ident", "")); } } return count; } }; struct StationData : public Base { StationData(DB& db, unsigned int modifiers) : Base(db, modifiers) {} ~StationData() {} void to_record(Record& rec) override { to_record_pseudoana(rec); to_record_repinfo(rec); if (results[cur].out_id_ltr == -1) rec.unset("context_id"); else rec.seti("context_id", results[cur].out_id_data); to_record_varcode(rec); rec.clear_vars(); rec.set(newvar(results[cur].out_varcode, results[cur].out_value)); } unsigned test_iterate(FILE* dump=0) override { //auto r = Record::create(); unsigned count; for (count = 0; next(); ++count) { if (dump) { /* to_record(r); fprintf(dump, "%02d %06d %06d %-10s\n", r.get(DBA_KEY_ANA_ID, -1), r.get(DBA_KEY_LAT, 0.0), r.get(DBA_KEY_LON, 0.0), r.get(DBA_KEY_IDENT, "")); */ } } return count; } wreport::Varcode get_varcode() const override { return (wreport::Varcode)results[cur].out_varcode; } wreport::Var get_var() const override { return Var(varinfo(results[cur].out_varcode), results[cur].out_value); } int attr_reference_id() const override { return results[cur].out_id_data; } }; struct Data : public Base { Data(DB& db, unsigned int modifiers) : Base(db, modifiers) {} ~Data() {} void to_record(Record& rec) override { to_record_pseudoana(rec); to_record_repinfo(rec); if (results[cur].out_id_ltr == -1) rec.unset("context_id"); else rec.seti("context_id", results[cur].out_id_data); to_record_varcode(rec); to_record_ltr(rec); to_record_datetime(rec); rec.clear_vars(); rec.set(newvar(results[cur].out_varcode, results[cur].out_value)); } unsigned test_iterate(FILE* dump=0) override { //auto r = Record::create(); unsigned count; for (count = 0; next(); ++count) { if (dump) { /* to_record(r); fprintf(dump, "%02d %06d %06d %-10s\n", r.get(DBA_KEY_ANA_ID, -1), r.get(DBA_KEY_LAT, 0.0), r.get(DBA_KEY_LON, 0.0), r.get(DBA_KEY_IDENT, "")); */ } } return count; } Level get_level() const override { return db.lev_tr_cache().to_level(results[cur].out_id_ltr); } Trange get_trange() const override { return db.lev_tr_cache().to_trange(results[cur].out_id_ltr); } Datetime get_datetime() const override { return results[cur].out_datetime; } wreport::Varcode get_varcode() const override { return (wreport::Varcode)results[cur].out_varcode; } wreport::Var get_var() const override { return Var(varinfo(results[cur].out_varcode), results[cur].out_value); } int attr_reference_id() const override { return results[cur].out_id_data; } #if 0 void Cursor::query_attrs(function&&)> dest) { db.query_attrs(results[cur].out_id_data, results[cur].out_varcode, dest); } void Cursor::attr_insert(const Values& attrs) { db.attr_insert(results[cur].out_id_data, results[cur].out_varcode, attrs); } void Cursor::attr_remove(const AttrList& qcs) { db.attr_remove(results[cur].out_id_data, results[cur].out_varcode, qcs); } #endif }; struct Summary : public Base { Summary(DB& db, unsigned int modifiers) : Base(db, modifiers) {} ~Summary() {} void to_record(Record& rec) override { to_record_pseudoana(rec); to_record_repinfo(rec); to_record_varcode(rec); to_record_ltr(rec); if (modifiers & DBA_DB_MODIFIER_SUMMARY_DETAILS) { rec.seti("context_id", results[cur].out_id_data); rec.set(DatetimeRange(results[cur].out_datetime, results[cur].out_datetimemax)); } } unsigned test_iterate(FILE* dump=0) override { auto r = Record::create(); unsigned count; for (count = 0; next(); ++count) { if (dump) { to_record(*r); fprintf(dump, "%02d %s %03d %s %04d-%02d-%02d %02d:%02d:%02d %04d-%02d-%02d %02d:%02d:%02d %d\n", r->enq("ana_id", -1), r->enq("rep_memo", ""), (int)results[cur].out_id_ltr, r->enq("var", ""), r->enq("yearmin", 0), r->enq("monthmin", 0), r->enq("daymin", 0), r->enq("hourmin", 0), r->enq("minumin", 0), r->enq("secmin", 0), r->enq("yearmax", 0), r->enq("monthmax", 0), r->enq("daymax", 0), r->enq("hourmax", 0), r->enq("minumax", 0), r->enq("secmax", 0), r->enq("limit", -1)); } } return count; } Level get_level() const override { return db.lev_tr_cache().to_level(results[cur].out_id_ltr); } Trange get_trange() const override { return db.lev_tr_cache().to_trange(results[cur].out_id_ltr); } DatetimeRange get_datetimerange() const override { return DatetimeRange(results[cur].out_datetime, results[cur].out_datetimemax); } wreport::Varcode get_varcode() const override { return (wreport::Varcode)results[cur].out_varcode; } size_t get_count() const override { return results[cur].out_id_data; } }; struct Best : public Base { Best(DB& db, unsigned int modifiers) : Base(db, modifiers) {} ~Best() {} void to_record(Record& rec) override { to_record_pseudoana(rec); to_record_repinfo(rec); if (results[cur].out_id_ltr == -1) rec.unset("context_id"); else rec.seti("context_id", results[cur].out_id_data); to_record_varcode(rec); to_record_ltr(rec); to_record_datetime(rec); rec.clear_vars(); rec.set(newvar(results[cur].out_varcode, results[cur].out_value)); } unsigned test_iterate(FILE* dump=0) override { // auto r = Record::create(); unsigned count; for (count = 0; next(); ++count) { /* if (dump) fprintf(dump, "%03d\n", (int)results[cur].out_id_data); */ } return count; } Level get_level() const override { return db.lev_tr_cache().to_level(results[cur].out_id_ltr); } Trange get_trange() const override { return db.lev_tr_cache().to_trange(results[cur].out_id_ltr); } Datetime get_datetime() const override { return results[cur].out_datetime; } wreport::Varcode get_varcode() const override { return (wreport::Varcode)results[cur].out_varcode; } wreport::Var get_var() const override { return Var(varinfo(results[cur].out_varcode), results[cur].out_value); } int attr_reference_id() const override { return results[cur].out_id_data; } void load(const QueryBuilder& qb) override { db::sql::Repinfo& ri = db.repinfo(); bool first = true; sql::SQLRecordV6 best; db.driver().run_built_query_v6(qb, [&](sql::SQLRecordV6& rec) { // Fill priority rec.priority = ri.get_priority(rec.out_rep_cod); // Filter results keeping only those with the best priority if (first) { // The first record initialises 'best' best = rec; first = false; } else if (rec.querybest_fields_are_the_same(best)) { // If they match, keep the record with the highest priority if (rec.priority > best.priority) best = rec; } else { // If they don't match, write out the previous best value results.append(best); // And restart with a new candidate best record for the next batch best = rec; } }); // Write out the last best value if (!first) results.append(best); // We are done adding, prepare the structbuf for reading results.ready_to_read(); } friend class Cursor; }; } unique_ptr run_station_query(DB& db, const core::Query& q, bool explain) { unsigned int modifiers = q.get_modifiers(); StationQueryBuilder qb(db, q, modifiers); qb.build(); if (explain) { fprintf(stderr, "EXPLAIN "); q.print(stderr); db.driver().explain(qb.sql_query); } auto resptr = new Stations(db, modifiers); unique_ptr res(resptr); resptr->load(qb); return res; } unique_ptr run_station_data_query(DB& db, const core::Query& q, bool explain) { unsigned int modifiers = q.get_modifiers(); DataQueryBuilder qb(db, q, modifiers, true); qb.build(); if (explain) { fprintf(stderr, "EXPLAIN "); q.print(stderr); db.driver().explain(qb.sql_query); } unique_ptr res; if (modifiers & DBA_DB_MODIFIER_BEST) { throw error_unimplemented("best queries of station vars"); //auto resptr = new Best(db, modifiers); //res.reset(resptr); //resptr->load(qb); } else { auto resptr = new StationData(db, modifiers); res.reset(resptr); resptr->load(qb); } return res; } unique_ptr run_data_query(DB& db, const core::Query& q, bool explain) { unsigned int modifiers = q.get_modifiers(); DataQueryBuilder qb(db, q, modifiers, false); qb.build(); if (explain) { fprintf(stderr, "EXPLAIN "); q.print(stderr); db.driver().explain(qb.sql_query); } unique_ptr res; if (modifiers & DBA_DB_MODIFIER_BEST) { auto resptr = new Best(db, modifiers); res.reset(resptr); resptr->load(qb); } else { auto resptr = new Data(db, modifiers); res.reset(resptr); resptr->load(qb); } return res; } unique_ptr run_summary_query(DB& db, const core::Query& q, bool explain) { unsigned int modifiers = q.get_modifiers(); if (modifiers & DBA_DB_MODIFIER_BEST) throw error_consistency("cannot use query=best on summary queries"); SummaryQueryBuilder qb(db, q, modifiers, false); qb.build(); if (explain) { fprintf(stderr, "EXPLAIN "); q.print(stderr); db.driver().explain(qb.sql_query); } auto resptr = new Summary(db, modifiers); unique_ptr res(resptr); resptr->load(qb); return res; } void run_delete_query(DB& db, const core::Query& q, bool station_vars, bool explain) { unsigned int modifiers = q.get_modifiers(); if (modifiers & DBA_DB_MODIFIER_BEST) throw error_consistency("cannot use query=best on summary queries"); IdQueryBuilder qb(db, q, modifiers, station_vars); qb.build(); if (explain) { fprintf(stderr, "EXPLAIN "); q.print(stderr); db.driver().explain(qb.sql_query); } db.data().remove(qb); } } } } } dballe-7.7/dballe/db/v6/import.cc0000644000175000017500000001330012652630043013515 00000000000000/* * db/v6/import - Import Msg data into the database * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "db.h" #include "dballe/db/sql.h" #include "dballe/db/sql/driver.h" #include "dballe/db/sql/station.h" #include "dballe/db/sql/levtr.h" #include "dballe/db/sql/datav6.h" #include "dballe/db/sql/attrv6.h" #include "dballe/msg/msg.h" #include "dballe/msg/context.h" using namespace wreport; namespace dballe { namespace db { namespace v6 { void DB::import_msg(const Message& message, const char* repmemo, int flags) { const Msg& msg = Msg::downcast(message); const msg::Context* l_ana = msg.find_context(Level(), Trange()); if (!l_ana) throw error_consistency("cannot import into the database a message without station information"); // Check if the station is mobile bool mobile = msg.get_ident_var() != NULL; sql::Station& st = station(); sql::LevTr& lt = lev_tr(); sql::DataV6& dd = data(); sql::AttrV6& dq = attr(); // Begin transaction auto t = conn->transaction(); // Fill up the pseudoana informations needed to fetch an existing ID // Latitude int lat; if (const Var* var = l_ana->find_by_id(DBA_MSG_LATITUDE)) lat = var->enqi(); else throw error_notfound("latitude not found in data to import"); // Longitude int lon; if (const Var* var = l_ana->find_by_id(DBA_MSG_LONGITUDE)) lon = var->enqi(); else throw error_notfound("longitude not found in data to import"); // Station identifier const char* ident = NULL; if (mobile) { if (const Var* var = l_ana->find_by_id(DBA_MSG_IDENT)) ident = var->enqc(); else throw error_notfound("mobile station identifier not found in data to import"); } bool inserted_pseudoana = false; int id_station = st.obtain_id(lat, lon, ident, &inserted_pseudoana); // Report code int id_report; if (repmemo != NULL) id_report = rep_cod_from_memo(repmemo); else { // TODO: check if B01194 first if (const Var* var = msg.get_rep_memo_var()) id_report = rep_cod_from_memo(var->enqc()); else id_report = rep_cod_from_memo(Msg::repmemo_from_type(msg.type)); } if ((flags & DBA_IMPORT_FULL_PSEUDOANA) || inserted_pseudoana) { // Prepare a bulk insert sql::bulk::InsertV6 vars; vars.id_station = id_station; vars.id_report = id_report; vars.datetime = Datetime(1000, 1, 1, 0, 0, 0); for (size_t i = 0; i < l_ana->data.size(); ++i) { Varcode code = l_ana->data[i]->code(); // Do not import datetime in the station info context if (code >= WR_VAR(0, 4, 1) && code <= WR_VAR(0, 4, 6)) continue; vars.add(l_ana->data[i], -1); } // Run the bulk insert dd.insert(*t, vars, (flags & DBA_IMPORT_OVERWRITE) ? sql::DataV6::UPDATE : sql::DataV6::IGNORE); // Insert the attributes if (flags & DBA_IMPORT_ATTRS) { #if 0 for (const auto& v: vars) if (v.inserted()) dq.add(v.id_data, *v.var); #else sql::bulk::InsertAttrsV6 attrs; for (const auto& v: vars) { if (!v.inserted()) continue; attrs.add_all(*v.var, v.id_data); } if (!attrs.empty()) dq.insert(*t, attrs, sql::AttrV6::UPDATE); #endif } } sql::bulk::InsertV6 vars; vars.id_station = id_station; vars.id_report = id_report; // Date and time if (msg.get_datetime().is_missing()) throw error_notfound("date/time informations not found (or incomplete) in message to insert"); vars.datetime = msg.get_datetime(); // Fill the bulk insert with the rest of the data for (size_t i = 0; i < msg.data.size(); ++i) { const msg::Context& ctx = *msg.data[i]; bool is_ana_level = ctx.level == Level() && ctx.trange == Trange(); // Skip the station info level if (is_ana_level) continue; // Get the database ID of the lev_tr int id_lev_tr = lt.obtain_id(ctx.level, ctx.trange); for (size_t j = 0; j < ctx.data.size(); ++j) { const Var* var = ctx.data[j]; if (not var->isset()) continue; vars.add(var, id_lev_tr); } } // Run the bulk insert dd.insert(*t, vars, (flags & DBA_IMPORT_OVERWRITE) ? sql::DataV6::UPDATE : sql::DataV6::IGNORE); // Insert the attributes if (flags & DBA_IMPORT_ATTRS) { #if 0 for (const auto& v: vars) if (v.inserted()) dq.add(v.id_data, *v.var); #else sql::bulk::InsertAttrsV6 attrs; for (const auto& v: vars) { if (!v.inserted()) continue; attrs.add_all(*v.var, v.id_data); } if (!attrs.empty()) dq.insert(*t, attrs, sql::AttrV6::UPDATE); #endif } t->commit(); } } } } dballe-7.7/dballe/db/v6/cursor.h0000644000175000017500000000130012652630043013357 00000000000000#ifndef DBA_DB_V6_CURSOR_H #define DBA_DB_V6_CURSOR_H #include #include namespace dballe { namespace core { struct Query; } namespace db { namespace v6 { namespace cursor { std::unique_ptr run_station_query(DB& db, const core::Query& query, bool explain); std::unique_ptr run_station_data_query(DB& db, const core::Query& query, bool explain); std::unique_ptr run_data_query(DB& db, const core::Query& query, bool explain); std::unique_ptr run_summary_query(DB& db, const core::Query& query, bool explain); void run_delete_query(DB& db, const core::Query& query, bool station_vars, bool explain); } } } } #endif dballe-7.7/dballe/db/v6/db.h0000644000175000017500000001743312652630043012445 00000000000000/* * dballe/v6/db - Archive for point-based meteorological data, db layout version 6 * * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBA_DB_V6_H #define DBA_DB_V6_H #include #include #include #include #include #include /** @file * @ingroup db * * Functions used to connect to DB-All.e and insert, query and delete data. */ /** * Constants used to define what values we should retrieve from a query */ /** Retrieve latitude and longitude */ #define DBA_DB_WANT_COORDS (1 << 0) /** Retrieve the mobile station identifier */ #define DBA_DB_WANT_IDENT (1 << 1) /** Retrieve the level information */ #define DBA_DB_WANT_LEVEL (1 << 2) /** Retrieve the time range information */ #define DBA_DB_WANT_TIMERANGE (1 << 3) /** Retrieve the date and time information */ #define DBA_DB_WANT_DATETIME (1 << 4) /** Retrieve the variable name */ #define DBA_DB_WANT_VAR_NAME (1 << 5) /** Retrieve the variable value */ #define DBA_DB_WANT_VAR_VALUE (1 << 6) /** Retrieve the report code */ #define DBA_DB_WANT_REPCOD (1 << 7) /** Retrieve the station ID */ #define DBA_DB_WANT_ANA_ID (1 << 8) /** Retrieve the lev_tr ID */ #define DBA_DB_WANT_CONTEXT_ID (1 << 9) namespace dballe { struct Station; struct StationValues; struct DataValues; namespace db { struct Connection; struct Statement; struct Sequence; namespace sql { struct Driver; struct Repinfo; struct Station; struct LevTr; struct LevTrCache; struct DataV6; struct AttrV6; } namespace v6 { /** * DB-ALLe database connection */ class DB : public dballe::DB { public: /// Database connection db::Connection* conn; /// Database query tracing Trace trace; /// True if we print an EXPLAIN trace of all queries to stderr bool explain_queries = false; protected: /// SQL driver backend sql::Driver* m_driver; /** * Accessors for the various parts of the database. * * @warning Before using these 5 pointers, ensure they are initialised * using one of the dba_db_need_* functions * @{ */ /** Report information */ struct sql::Repinfo* m_repinfo; /** Station information */ struct sql::Station* m_station; /** Level/timerange information */ struct sql::LevTr* m_lev_tr; /// Level/timerange cache struct sql::LevTrCache* m_lev_tr_cache; /** Variable data */ struct sql::DataV6* m_data; /** Variable attributes */ struct sql::AttrV6* m_attr; /** @} */ void init_after_connect(); DB(std::unique_ptr conn); /* * Lookup, insert or replace data in station taking the values from * rec. * * If rec did not contain ana_id, it will be set by this function. * * @param rec * The record with the station information * @param can_add * If true we can insert new stations in the database, if false we * only look up existing records and raise an exception if missing * @returns * The station ID */ int obtain_station(const Station& st, bool can_add=true); public: virtual ~DB(); db::Format format() const { return V6; } /// Access the backend DB driver sql::Driver& driver(); /// Access the repinfo table sql::Repinfo& repinfo(); /// Access the station table sql::Station& station(); /// Access the lev_tr table sql::LevTr& lev_tr(); /// Access the lev_tr cache sql::LevTrCache& lev_tr_cache(); /// Access the data table sql::DataV6& data(); /// Access the data table sql::AttrV6& attr(); void disappear(); /** * Reset the database, removing all existing DBALLE tables and re-creating them * empty. * * @param repinfo_file * The name of the CSV file with the report type information data to load. * The file is in CSV format with 6 columns: report code, mnemonic id, * description, priority, descriptor, table A category. * If repinfo_file is NULL, then the default of /etc/dballe/repinfo.csv is * used. */ void reset(const char* repinfo_file = 0); /** * Delete all the DB-ALLe tables from the database. */ void delete_tables(); /** * Update the repinfo table in the database, with the data found in the given * file. * * @param repinfo_file * The name of the CSV file with the report type information data to load. * The file is in CSV format with 6 columns: report code, mnemonic id, * description, priority, descriptor, table A category. * If repinfo_file is NULL, then the default of /etc/dballe/repinfo.csv is * used. * @retval added * The number of repinfo entryes that have been added * @retval deleted * The number of repinfo entryes that have been deleted * @retval updated * The number of repinfo entryes that have been updated */ void update_repinfo(const char* repinfo_file, int* added, int* deleted, int* updated); std::map get_repinfo_priorities(); /** * Get the report code from a report mnemonic */ int rep_cod_from_memo(const char* memo); void insert_station_data(StationValues& vals, bool can_replace, bool station_can_add) override; void insert_data(DataValues& vals, bool can_replace, bool station_can_add) override; void remove_station_data(const Query& query) override; void remove(const Query& query); void remove_all(); /** * Remove orphan values from the database. * * Orphan values are currently: * \li lev_tr values for which no data exists * \li station values for which no lev_tr exists * * Depending on database size, this routine can take a few minutes to execute. */ void vacuum(); std::unique_ptr query_stations(const Query& query); std::unique_ptr query_station_data(const Query& query) override; std::unique_ptr query_data(const Query& query); std::unique_ptr query_summary(const Query& query); void attr_query_station(int data_id, std::function)>&& dest) override; void attr_query_data(int data_id, std::function)>&& dest) override; void attr_insert_station(int data_id, const Values& attrs) override; void attr_insert_data(int data_id, const Values& attrs) override; void attr_remove_station(int data_id, const db::AttrList& qcs) override; void attr_remove_data(int data_id, const db::AttrList& qcs) override; bool is_station_variable(int data_id, wreport::Varcode varcode) override; void import_msg(const Message& msg, const char* repmemo, int flags) override; bool export_msgs(const Query& query, std::function&&)> dest) override; /** * Dump the entire contents of the database to an output stream */ void dump(FILE* out); friend class dballe::DB; }; } // namespace v6 } // namespace db } // namespace dballe /* vim:set ts=4 sw=4: */ #endif dballe-7.7/dballe/db/db-import-bench.cc0000644000175000017500000000500512652630043014625 00000000000000#include "dballe/db/bench.h" #include "dballe/core/file.h" #include "dballe/msg/msg.h" #include "dballe/msg/codec.h" using namespace dballe; using namespace std; using namespace wreport; namespace { struct MsgCollector : public vector { ~MsgCollector() { for (iterator i = begin(); i != end(); ++i) delete *i; } void read(File::Encoding type, const std::string& fname) { dballe::msg::Importer::Options opts; std::unique_ptr importer = msg::Importer::create(type, opts); unique_ptr f = core::File::open_test_data_file(type, fname); f->foreach([&](const BinaryMessage& rmsg) { importer->foreach_decoded(rmsg, [&](unique_ptr&& m) { push_back(m.release()); return true; }); return true; }); } }; struct B : bench::DBBenchmark { benchmark::Task synop; benchmark::Task temp; benchmark::Task flight; MsgCollector samples_synop; MsgCollector samples_temp; MsgCollector samples_flight; B(const std::string& name) : bench::DBBenchmark::DBBenchmark(name), synop(this, "synop"), temp(this, "temp"), flight(this, "airplane") { repetitions = 10; } void setup_main() { bench::DBBenchmark::setup_main(); // Read samples for (auto& fn : { "synop-cloudbelow.bufr", "synop-evapo.bufr", "synop-groundtemp.bufr", "synop-gtscosmo.bufr", "synop-longname.bufr" }) samples_synop.read(File::BUFR, string("bufr/") + fn); for (auto& fn : { "temp-gts1.bufr", "temp-gts2.bufr", "temp-gts3.bufr", "temp-gtscosmo.bufr", "temp-timesig18.bufr" }) samples_temp.read(File::BUFR, string("bufr/") + fn); for (auto& fn : { "gts-acars1.bufr", "gts-acars2.bufr", "gts-acars-us1.bufr", "gts-amdar1.bufr", "gts-amdar2.bufr" }) samples_flight.read(File::BUFR, string("bufr/") + fn); } void main() override { synop.collect([&]() { for (auto& m: samples_synop) db->import_msg(*m, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); }); temp.collect([&]() { for (auto& m: samples_temp) db->import_msg(*m, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); }); flight.collect([&]() { for (auto& m: samples_flight) db->import_msg(*m, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); }); } } test("db_import"); } dballe-7.7/dballe/db/querybuf.cc0000644000175000017500000000533612652630043013524 00000000000000/* * db/querybuf - Buffer used to build SQL queries * * Copyright (C) 2005--2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "querybuf.h" #include #include #include #include #include "dballe/core/vasprintf.h" #include "dballe/var.h" using namespace std; using namespace wreport; namespace dballe { Querybuf::Querybuf(size_t reserve) { clear(); this->reserve(512); } Querybuf::~Querybuf() {} void Querybuf::clear() { string::clear(); list_first = true; list_sep[0] = 0; } void Querybuf::start_list(const char* sep) { list_first = true; strncpy(list_sep, sep, 10); list_sep[9] = 0; } void Querybuf::appendf(const char* fmt, ...) { va_list ap; va_start(ap, fmt); char* buf; int size = vasprintf(&buf, fmt, ap); append(buf, size); free(buf); va_end(ap); } void Querybuf::append_list(const char* str) { if (list_first) list_first = false; else append(list_sep); append(str); } void Querybuf::append_listf(const char* fmt, ...) { va_list ap; va_start(ap, fmt); if (list_first) list_first = false; else append(list_sep); char* buf; int size = vasprintf(&buf, fmt, ap); append(buf, size); free(buf); va_end(ap); } void Querybuf::append_varlist(const std::string& varlist) { size_t pos = 0; while (true) { size_t end = varlist.find(',', pos); Varcode code; if (end == string::npos) code = resolve_varcode(varlist.substr(pos)); else code = resolve_varcode(varlist.substr(pos, end - pos)); if (pos == 0) appendf("%d", code); else appendf(",%d", code); if (end == string::npos) break; pos = end + 1; } } void Querybuf::append_varlist(const std::set& varlist) { bool first = true; for (const auto& v : varlist) { if (first) { appendf("%d", (int)v); first = false; } else appendf(",%d", (int)v); } } } /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/db/postgresql/0000755000175000017500000000000012653425050013630 500000000000000dballe-7.7/dballe/db/postgresql/internals-test.cc0000644000175000017500000002131112652630043017030 00000000000000#include "db/tests.h" #include "internals.h" using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct ConnectorFixture : public Fixture { PostgreSQLConnection conn; ConnectorFixture() { conn.open_test(); } void test_setup() { Fixture::test_setup(); conn.drop_table_if_exists("dballe_test"); conn.exec_no_data("CREATE TABLE dballe_test (val INTEGER NOT NULL)"); } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("int", [](Fixture& f) { // Test querying int values auto& conn = f.conn; conn.exec_no_data("INSERT INTO dballe_test VALUES (1)"); conn.exec_no_data("INSERT INTO dballe_test VALUES (2)"); auto s = conn.exec("SELECT val FROM dballe_test"); wassert(actual(s.rowcount()) == 2); int val = 0; for (unsigned row = 0; row < 2; ++row) val += s.get_int4(row, 0); wassert(actual(val) == 3); }); add_method("int_null", [](Fixture& f) { // Test querying int values, with potential NULLs auto& conn = f.conn; conn.drop_table_if_exists("dballe_testnull"); conn.exec_no_data("CREATE TABLE dballe_testnull (val INTEGER)"); conn.exec_no_data("INSERT INTO dballe_testnull VALUES (NULL)"); conn.exec_no_data("INSERT INTO dballe_testnull VALUES (42)"); auto s = conn.exec("SELECT val FROM dballe_testnull"); wassert(actual(s.rowcount()) == 2); int val = 0; unsigned countnulls = 0; for (unsigned row = 0; row < 2; ++row) { if (s.is_null(row, 0)) ++countnulls; else val += s.get_int4(row, 0); } wassert(actual(val) == 42); wassert(actual(countnulls) == 1); }); add_method("unsigned", [](Fixture& f) { // Test querying unsigned values auto& conn = f.conn; conn.drop_table_if_exists("dballe_testbig"); conn.exec_no_data("CREATE TABLE dballe_testbig (val BIGINT)"); conn.exec_no_data("INSERT INTO dballe_testbig VALUES (x'FFFFFFFE'::bigint)"); auto s = conn.exec("SELECT val FROM dballe_testbig"); wassert(actual(s.rowcount()) == 1); unsigned val = 0; for (unsigned row = 0; row < 1; ++row) val += s.get_int8(row, 0); wassert(actual(val) == 0xFFFFFFFE); }); add_method("unsigned_short", [](Fixture& f) { // Test querying unsigned short values auto& conn = f.conn; conn.drop_table_if_exists("dballe_testshort"); conn.exec_no_data("CREATE TABLE dballe_testshort (val SMALLINT)"); conn.exec_no_data("INSERT INTO dballe_testshort VALUES (123)"); auto s = conn.exec("SELECT val FROM dballe_testshort"); wassert(actual(s.rowcount()) == 1); Varcode val = 0; for (unsigned row = 0; row < 1; ++row) val += s.get_int2(row, 0); wassert(actual(val) == 123); }); add_method("has_tables", [](Fixture& f) { // Test has_tables auto& conn = f.conn; wassert(actual(conn.has_table("this_should_not_exist")).isfalse()); wassert(actual(conn.has_table("dballe_test")).istrue()); }); add_method("settings", [](Fixture& f) { // Test settings auto& conn = f.conn; conn.drop_table_if_exists("dballe_settings"); wassert(actual(conn.has_table("dballe_settings")).isfalse()); wassert(actual(conn.get_setting("test_key")) == ""); conn.set_setting("test_key", "42"); wassert(actual(conn.has_table("dballe_settings")).istrue()); wassert(actual(conn.get_setting("test_key")) == "42"); wassert(actual(conn.get_setting("test_key1")) == ""); }); add_method("autoid", [](Fixture& f) { // Test auto_increment auto& conn = f.conn; conn.drop_table_if_exists("dballe_testai"); conn.exec_no_data("CREATE TABLE dballe_testai (id SERIAL PRIMARY KEY, val INTEGER)"); auto r1 = conn.exec_one_row("INSERT INTO dballe_testai (id, val) VALUES (DEFAULT, 42) RETURNING id"); wassert(actual(r1.get_int4(0, 0)) == 1); auto r2 = conn.exec_one_row("INSERT INTO dballe_testai (id, val) VALUES (DEFAULT, 43) RETURNING id"); wassert(actual(r2.get_int4(0, 0)) == 2); }); add_method("prepared", [](Fixture& f) { // Test prepared statements auto& conn = f.conn; conn.exec_no_data("INSERT INTO dballe_test VALUES (1)"); conn.exec_no_data("INSERT INTO dballe_test VALUES (2)"); conn.prepare("db_postgresql_internals_9", "SELECT val FROM dballe_test"); auto s = conn.exec_prepared("db_postgresql_internals_9"); wassert(actual(s.rowcount()) == 2); int val = 0; for (unsigned row = 0; row < 2; ++row) val += s.get_int4(row, 0); wassert(actual(val) == 3); }); add_method("prepared_int", [](Fixture& f) { // Test prepared statements with int arguments auto& conn = f.conn; conn.exec_no_data("INSERT INTO dballe_test VALUES (1)"); conn.exec_no_data("INSERT INTO dballe_test VALUES (2)"); conn.prepare("db_postgresql_internals_10", "SELECT val FROM dballe_test WHERE val=$1::int4"); auto res = conn.exec_prepared("db_postgresql_internals_10", 1); wassert(actual(res.rowcount()) == 1); wassert(actual(res.get_int4(0, 0)) == 1); }); add_method("prepared_string", [](Fixture& f) { // Test prepared statements with string arguments auto& conn = f.conn; conn.drop_table_if_exists("db_postgresql_internals_11"); conn.exec_no_data("CREATE TABLE db_postgresql_internals_11 (val TEXT)"); conn.exec_no_data("INSERT INTO db_postgresql_internals_11 VALUES ('foo')"); conn.exec_no_data("INSERT INTO db_postgresql_internals_11 VALUES ('bar')"); conn.prepare("db_postgresql_internals_11_select", "SELECT val FROM db_postgresql_internals_11 WHERE val=$1::text"); auto res1 = conn.exec_prepared("db_postgresql_internals_11_select", "foo"); wassert(actual(res1.rowcount()) == 1); wassert(actual(res1.get_string(0, 0)) == "foo"); auto res2 = conn.exec_prepared("db_postgresql_internals_11_select", string("foo")); wassert(actual(res2.rowcount()) == 1); wassert(actual(res2.get_string(0, 0)) == "foo"); }); add_method("prepared_datetime", [](Fixture& f) { // Test prepared statements with datetime arguments auto& conn = f.conn; conn.drop_table_if_exists("db_postgresql_internals_12"); conn.exec_no_data("CREATE TABLE db_postgresql_internals_12 (val TIMESTAMP)"); conn.exec_no_data("INSERT INTO db_postgresql_internals_12 VALUES ('2015-04-01 12:30:45')"); conn.exec_no_data("INSERT INTO db_postgresql_internals_12 VALUES ('1945-04-25 08:10:20')"); conn.prepare("db_postgresql_internals_12_select", "SELECT val FROM db_postgresql_internals_12 WHERE val=$1::timestamp"); auto res1 = conn.exec("SELECT val FROM db_postgresql_internals_12 WHERE val=TIMESTAMP '2015-04-01 12:30:45'"); wassert(actual(res1.rowcount()) == 1); wassert(actual(res1.get_timestamp(0, 0)) == Datetime(2015, 4, 1, 12, 30, 45)); auto res2 = conn.exec_prepared("db_postgresql_internals_12_select", Datetime(2015, 4, 1, 12, 30, 45)); wassert(actual(res2.rowcount()) == 1); wassert(actual(res2.get_timestamp(0, 0)) == Datetime(2015, 4, 1, 12, 30, 45)); auto res3 = conn.exec("SELECT val FROM db_postgresql_internals_12 WHERE val=TIMESTAMP '1945-04-25 08:10:20'"); wassert(actual(res3.rowcount()) == 1); wassert(actual(res3.get_timestamp(0, 0)) == Datetime(1945, 4, 25, 8, 10, 20)); auto res4 = conn.exec_prepared("db_postgresql_internals_12_select", Datetime(1945, 4, 25, 8, 10, 20)); wassert(actual(res4.rowcount()) == 1); wassert(actual(res4.get_timestamp(0, 0)) == Datetime(1945, 4, 25, 8, 10, 20)); }); } } test("db_postgresql_internals"); } dballe-7.7/dballe/db/postgresql/repinfo.cc0000644000175000017500000001122412652630043015520 00000000000000/* * db/postgresql/repinfo - repinfo table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "repinfo.h" #include "dballe/db/db.h" #include "dballe/db/postgresql/internals.h" #include "dballe/db/querybuf.h" using namespace wreport; using namespace std; namespace dballe { namespace db { namespace postgresql { PostgreSQLRepinfoBase::PostgreSQLRepinfoBase(PostgreSQLConnection& conn) : Repinfo(conn), conn(conn) { read_cache(); } PostgreSQLRepinfoBase::~PostgreSQLRepinfoBase() { } void PostgreSQLRepinfoBase::read_cache() { cache.clear(); memo_idx.clear(); auto stm = conn.exec("SELECT id, memo, description, prio, descriptor, tablea FROM repinfo ORDER BY id"); for (unsigned row = 0; row < stm.rowcount(); ++row) { cache_append( stm.get_int4(row, 0), stm.get_string(row, 1), stm.get_string(row, 2), stm.get_int4(row, 3), stm.get_string(row, 4), stm.get_int4(row, 5) ); } // Rebuild the memo index as well rebuild_memo_idx(); } void PostgreSQLRepinfoBase::insert_auto_entry(const char* memo) { unsigned id = conn.exec_one_row("SELECT MAX(id) FROM repinfo").get_int4(0, 0); int prio = conn.exec_one_row("SELECT MAX(prio) FROM repinfo").get_int4(0, 0); ++id; ++prio; Querybuf query(500); query.appendf(R"( INSERT INTO repinfo (id, memo, description, prio, descriptor, tablea) VALUES (%u, $1::text, $1::text, %d, '-', 255) )", id, prio); conn.exec_no_data(query, memo); } int PostgreSQLRepinfoBase::id_use_count(unsigned id, const char* name) { Querybuf query(500); query.appendf("SELECT COUNT(1) FROM context WHERE id_report=%u", id); return conn.exec_one_row(query).get_int4(0, 0); } void PostgreSQLRepinfoBase::delete_entry(unsigned id) { conn.exec_no_data("DELETE FROM repinfo WHERE id=$1::int4", (int32_t)id); } void PostgreSQLRepinfoBase::update_entry(const sql::repinfo::Cache& entry) { conn.exec_no_data(R"( UPDATE repinfo SET memo=$2::text, description=$3::text, prio=$4::int4, descriptor=$5::text, tablea=$6::int4 WHERE id=$1::int4 )", (int32_t)entry.id, entry.new_memo, entry.new_desc, (int32_t)entry.new_prio, entry.new_descriptor, (int32_t)entry.new_tablea); } void PostgreSQLRepinfoBase::insert_entry(const sql::repinfo::Cache& entry) { conn.exec_no_data(R"( INSERT INTO repinfo (id, memo, description, prio, descriptor, tablea) VALUES ($1::int4, $2::text, $3::text, $4::int4, $5::text, $6::int4) )", (int32_t)entry.id, entry.new_memo, entry.new_desc, (int32_t)entry.new_prio, entry.new_descriptor, (int32_t)entry.new_tablea); } void PostgreSQLRepinfoBase::dump(FILE* out) { fprintf(out, "dump of table repinfo:\n"); fprintf(out, " id memo description prio desc tablea\n"); int count = 0; auto stm = conn.exec("SELECT id, memo, description, prio, descriptor, tablea FROM repinfo ORDER BY id"); for (unsigned row = 0; row < stm.rowcount(); ++row) { string memo = stm.get_string(row, 1); string desc = stm.get_string(row, 2); string descriptor = stm.get_string(row, 4); fprintf(out, " %4d %s %s %d %s %d\n", stm.get_int4(row, 0), memo.c_str(), desc.c_str(), stm.get_int4(row, 3), descriptor.c_str(), stm.get_int4(row, 5)); ++count; }; fprintf(out, "%d element%s in table repinfo\n", count, count != 1 ? "s" : ""); } PostgreSQLRepinfoV6::PostgreSQLRepinfoV6(PostgreSQLConnection& conn) : PostgreSQLRepinfoBase(conn) {} int PostgreSQLRepinfoV6::id_use_count(unsigned id, const char* name) { Querybuf query(500); query.appendf("SELECT COUNT(1) FROM data WHERE id_report=%u", id); return conn.exec_one_row(query).get_int4(0, 0); } } } } dballe-7.7/dballe/db/postgresql/levtr.h0000644000175000017500000000411612652630043015056 00000000000000/* * db/lev_tr - lev_tr table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_POSTGRESQL_LEV_TR_H #define DBALLE_DB_POSTGRESQL_LEV_TR_H #include #include #include #include #include namespace dballe { struct Record; struct Msg; namespace msg { struct Context; } namespace db { struct Connection; struct Statement; namespace postgresql { struct DB; /** * Precompiled queries to manipulate the lev_tr table */ struct PostgreSQLLevTrV6 : public sql::LevTr { protected: /** * DB connection. */ PostgreSQLConnection& conn; DBRow working_row; public: PostgreSQLLevTrV6(PostgreSQLConnection& conn); PostgreSQLLevTrV6(const LevTr&) = delete; PostgreSQLLevTrV6(const LevTr&&) = delete; PostgreSQLLevTrV6& operator=(const PostgreSQLLevTrV6&) = delete; ~PostgreSQLLevTrV6(); /** * Return the ID for the given Level and Trange, adding it to the database * if it does not already exist */ int obtain_id(const Level& lev, const Trange& tr) override; const DBRow* read(int id) override; void read_all(std::function dest) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/postgresql/driver.cc0000644000175000017500000002541212652630043015355 00000000000000/* * db/postgresql/driver - Backend PostgreSQL driver * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "driver.h" #include "repinfo.h" #include "station.h" #include "levtr.h" #include "datav6.h" #include "attrv6.h" #include "dballe/db/v6/qbuilder.h" #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace postgresql { Driver::Driver(PostgreSQLConnection& conn) : conn(conn) { } Driver::~Driver() { } std::unique_ptr Driver::create_repinfov6() { return unique_ptr(new PostgreSQLRepinfoV6(conn)); } std::unique_ptr Driver::create_stationv6() { return unique_ptr(new PostgreSQLStationV6(conn)); } std::unique_ptr Driver::create_levtrv6() { return unique_ptr(new PostgreSQLLevTrV6(conn)); } std::unique_ptr Driver::create_datav6() { return unique_ptr(new PostgreSQLDataV6(conn)); } std::unique_ptr Driver::create_attrv6() { return unique_ptr(new PostgreSQLAttrV6(conn)); } void Driver::run_built_query_v6( const v6::QueryBuilder& qb, std::function dest) { using namespace dballe::db::postgresql; // fprintf(stderr, "QUERY %d %s\n", qb.bind_in_ident, qb.sql_query.c_str()); // Start the query asynchronously int res; if (qb.bind_in_ident) { const char* args[1] = { qb.bind_in_ident }; res = PQsendQueryParams(conn, qb.sql_query.c_str(), 1, nullptr, args, nullptr, nullptr, 1); } else { res = PQsendQueryParams(conn, qb.sql_query.c_str(), 0, nullptr, nullptr, nullptr, nullptr, 1); } if (!res) throw error_postgresql(conn, "executing " + qb.sql_query); // http://www.postgresql.org/docs/9.4/static/libpq-single-row-mode.html if (!PQsetSingleRowMode(conn)) { string errmsg(PQerrorMessage(conn)); conn.cancel_running_query_nothrow(); conn.discard_all_input_nothrow(); throw error_postgresql(errmsg, "cannot set single row mode for query " + qb.sql_query); } sql::SQLRecordV6 rec; while (true) { Result res(PQgetResult(conn)); if (!res) break; // Note: Even when PQresultStatus indicates a fatal error, PQgetResult // should be called until it returns a null pointer to allow libpq to // process the error information completely. // (http://www.postgresql.org/docs/9.1/static/libpq-async.html) // If we get what we don't want, cancel, flush our input and throw if (PQresultStatus(res) == PGRES_SINGLE_TUPLE) { // Ok, we have a tuple } else if (PQresultStatus(res) == PGRES_TUPLES_OK) { // No more rows will arrive continue; } else { // An error arrived conn.cancel_running_query_nothrow(); conn.discard_all_input_nothrow(); switch (PQresultStatus(res)) { case PGRES_COMMAND_OK: throw error_postgresql("command_ok", "no data returned by query " + qb.sql_query); default: throw error_postgresql(res, "executing " + qb.sql_query); } } // fprintf(stderr, "ST %d vi %d did %d d %d sd %d\n", qb.select_station, qb.select_varinfo, qb.select_data_id, qb.select_data, qb.select_summary_details); for (unsigned row = 0; row < res.rowcount(); ++row) { int output_seq = 0; if (qb.select_station) { rec.out_ana_id = res.get_int4(row, output_seq++); rec.out_lat = res.get_int4(row, output_seq++); rec.out_lon = res.get_int4(row, output_seq++); if (res.is_null(row, output_seq)) { rec.out_ident_size = -1; rec.out_ident[0] = 0; } else { const char* ident = res.get_string(row, output_seq); rec.out_ident_size = min(PQgetlength(res, row, output_seq), 63); memcpy(rec.out_ident, ident, rec.out_ident_size); rec.out_ident[rec.out_ident_size] = 0; } ++output_seq; } if (qb.select_varinfo) { rec.out_rep_cod = res.get_int4(row, output_seq++); rec.out_id_ltr = res.get_int4(row, output_seq++); rec.out_varcode = res.get_int4(row, output_seq++); } if (qb.select_data_id) rec.out_id_data = res.get_int4(row, output_seq++); if (qb.select_data) { rec.out_datetime = res.get_timestamp(row, output_seq++); int value_len = min(PQgetlength(res, row, output_seq), 255); const char* value = res.get_string(row, output_seq++); memcpy(rec.out_value, value, value_len); rec.out_value[value_len] = 0; } if (qb.select_summary_details) { rec.out_id_data = res.get_int8(row, output_seq++); rec.out_datetime = res.get_timestamp(row, output_seq++); rec.out_datetimemax = res.get_timestamp(row, output_seq++); } // rec.dump(stderr); try { dest(rec); } catch (std::exception& e) { // If we get an exception from downstream, cancel, flush all // input and rethrow it conn.cancel_running_query_nothrow(); conn.discard_all_input_nothrow(); throw; } } } } void Driver::create_tables_v6() { conn.exec_no_data(R"( CREATE TABLE station ( id SERIAL PRIMARY KEY, lat INTEGER NOT NULL, lon INTEGER NOT NULL, ident VARCHAR(64) ); )"); conn.exec_no_data("CREATE UNIQUE INDEX pa_uniq ON station(lat, lon, ident);"); conn.exec_no_data("CREATE INDEX pa_lon ON station(lon);"); conn.exec_no_data(R"( CREATE TABLE repinfo ( id INTEGER PRIMARY KEY, memo VARCHAR(30) NOT NULL, description VARCHAR(255) NOT NULL, prio INTEGER NOT NULL, descriptor CHAR(6) NOT NULL, tablea INTEGER NOT NULL ); )"); conn.exec_no_data("CREATE UNIQUE INDEX ri_memo_uniq ON repinfo(memo);"); conn.exec_no_data("CREATE UNIQUE INDEX ri_prio_uniq ON repinfo(prio);"); conn.exec_no_data(R"( CREATE TABLE lev_tr ( id SERIAL PRIMARY KEY, ltype1 INTEGER NOT NULL, l1 INTEGER NOT NULL, ltype2 INTEGER NOT NULL, l2 INTEGER NOT NULL, ptype INTEGER NOT NULL, p1 INTEGER NOT NULL, p2 INTEGER NOT NULL ); )"); conn.exec_no_data("CREATE UNIQUE INDEX lev_tr_uniq ON lev_tr(ltype1, l1, ltype2, l2, ptype, p1, p2);"); conn.exec_no_data(R"( CREATE TABLE data ( id SERIAL PRIMARY KEY, id_station INTEGER NOT NULL REFERENCES station (id) ON DELETE CASCADE, id_report INTEGER NOT NULL REFERENCES repinfo (id) ON DELETE CASCADE, id_lev_tr INTEGER NOT NULL, datetime TIMESTAMP NOT NULL, id_var INTEGER NOT NULL, value VARCHAR(255) NOT NULL ); )"); conn.exec_no_data("CREATE UNIQUE INDEX data_uniq on data(id_station, datetime, id_lev_tr, id_report, id_var);"); conn.exec_no_data("CREATE INDEX data_ana ON data(id_station);"); conn.exec_no_data("CREATE INDEX data_report ON data(id_report);"); conn.exec_no_data("CREATE INDEX data_dt ON data(datetime);"); conn.exec_no_data("CREATE INDEX data_lt ON data(id_lev_tr);"); conn.exec_no_data(R"( CREATE TABLE attr ( id_data INTEGER NOT NULL REFERENCES data (id) ON DELETE CASCADE, type INTEGER NOT NULL, value VARCHAR(255) NOT NULL ); )"); conn.exec_no_data("CREATE UNIQUE INDEX attr_uniq ON attr(id_data, type);"); /* * Not a good idea: it works on ALL inserts, even on those that should fail "CREATE RULE data_insert_or_update AS " " ON INSERT TO data " " WHERE (new.id_context, new.id_var) IN ( " " SELECT id_context, id_var " " FROM data " " WHERE id_context=new.id_context AND id_var=new.id_var) " " DO INSTEAD " " UPDATE data SET value=new.value " " WHERE id_context=new.id_context AND id_var=new.id_var", */ /*"CREATE FUNCTION identity (val anyelement, val1 anyelement, OUT val anyelement) AS 'select $2' LANGUAGE sql STRICT", "CREATE AGGREGATE anyval ( basetype=anyelement, sfunc='identity', stype='anyelement' )",*/ conn.set_setting("version", "V6"); } void Driver::delete_tables_v6() { conn.drop_table_if_exists("attr"); conn.drop_table_if_exists("data"); conn.drop_table_if_exists("lev_tr"); conn.drop_table_if_exists("repinfo"); conn.drop_table_if_exists("station"); conn.drop_settings(); } void Driver::vacuum_v6() { conn.exec_no_data(R"( DELETE FROM lev_tr WHERE id IN ( SELECT ltr.id FROM lev_tr ltr LEFT JOIN data d ON d.id_lev_tr = ltr.id WHERE d.id_lev_tr is NULL) )"); conn.exec_no_data(R"( DELETE FROM station WHERE id IN ( SELECT p.id FROM station p LEFT JOIN data d ON d.id_station = p.id WHERE d.id is NULL) )"); } void Driver::exec_no_data(const std::string& query) { conn.exec_no_data(query); } void Driver::explain(const std::string& query) { using namespace dballe::db::postgresql; string explain_query = "EXPLAIN "; explain_query += query; fprintf(stderr, "%s\n", explain_query.c_str()); Result res = conn.exec(explain_query); for (unsigned row = 0; row < res.rowcount(); ++row) fprintf(stderr, " %s\n", res.get_string(row, 0)); } } } } dballe-7.7/dballe/db/postgresql/repinfo.h0000644000175000017500000000444712652630043015373 00000000000000/* * db/postgresql/repinfo - repinfo table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_POSTGRESQL_REPINFO_H #define DBALLE_DB_POSTGRESQL_REPINFO_H /** @file * @ingroup db * * Repinfo table management used by the db module. */ #include #include #include #include namespace dballe { struct Record; namespace db { struct PostgreSQLConnection; namespace postgresql { /** * Fast cached access to the repinfo table */ struct PostgreSQLRepinfoBase : public sql::Repinfo { /** * DB connection. The pointer is assumed always valid during the * lifetime of the object */ PostgreSQLConnection& conn; PostgreSQLRepinfoBase(PostgreSQLConnection& conn); PostgreSQLRepinfoBase(const PostgreSQLRepinfoBase&) = delete; PostgreSQLRepinfoBase(const PostgreSQLRepinfoBase&&) = delete; virtual ~PostgreSQLRepinfoBase(); PostgreSQLRepinfoBase& operator=(const PostgreSQLRepinfoBase&) = delete; void dump(FILE* out) override; protected: int id_use_count(unsigned id, const char* name) override; void delete_entry(unsigned id) override; void update_entry(const sql::repinfo::Cache& entry) override; void insert_entry(const sql::repinfo::Cache& entry) override; void read_cache() override; void insert_auto_entry(const char* memo) override; }; struct PostgreSQLRepinfoV6 : public PostgreSQLRepinfoBase { PostgreSQLRepinfoV6(PostgreSQLConnection& conn); protected: int id_use_count(unsigned id, const char* name) override; }; } } } #endif dballe-7.7/dballe/db/postgresql/levtr.cc0000644000175000017500000001052612652630043015216 00000000000000#include "levtr.h" #include "dballe/db/postgresql/internals.h" #include "dballe/core/defs.h" #include "dballe/msg/msg.h" #include #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace postgresql { namespace { Level to_level(const postgresql::Result& res, unsigned row, int first_id) { return Level( res.get_int4(row, first_id), res.get_int4(row, first_id + 1), res.get_int4(row, first_id + 2), res.get_int4(row, first_id + 3)); } Trange to_trange(const postgresql::Result& res, unsigned row, int first_id) { return Trange( res.get_int4(row, first_id), res.get_int4(row, first_id + 1), res.get_int4(row, first_id + 2)); } } PostgreSQLLevTrV6::PostgreSQLLevTrV6(PostgreSQLConnection& conn) : conn(conn) { conn.prepare("v6_levtr_select_id", R"( SELECT id FROM lev_tr WHERE ltype1=$1::int4 AND l1=$2::int4 AND ltype2=$3::int4 AND l2=$4::int4 AND ptype=$5::int4 AND p1=$6::int4 AND p2=$7::int4 )"); conn.prepare("v6_levtr_select_data", "SELECT ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr WHERE id=$1::int4"); conn.prepare("v6_levtr_insert", R"( INSERT INTO lev_tr (id, ltype1, l1, ltype2, l2, ptype, p1, p2) VALUES (DEFAULT, $1::int4, $2::int4, $3::int4, $4::int4, $5::int4, $6::int4, $7::int4) RETURNING id )"); } PostgreSQLLevTrV6::~PostgreSQLLevTrV6() { } int PostgreSQLLevTrV6::obtain_id(const Level& lev, const Trange& tr) { using namespace postgresql; Result res = conn.exec_prepared("v6_levtr_select_id", lev.ltype1, lev.l1, lev.ltype2, lev.l2, tr.pind, tr.p1, tr.p2); switch (res.rowcount()) { case 0: break; case 1: // If there is an existing record, use its ID and don't do an INSERT return res.get_int4(0, 0); default: error_consistency::throwf("select levtr ID query returned %u results", res.rowcount()); } return conn.exec_prepared_one_row("v6_levtr_insert", lev.ltype1, lev.l1, lev.ltype2, lev.l2, tr.pind, tr.p1, tr.p2).get_int4(0, 0); } const sql::LevTr::DBRow* PostgreSQLLevTrV6::read(int id) { auto res = conn.exec_prepared("v6_levtr_select_data", id); switch (res.rowcount()) { case 0: return nullptr; case 1: working_row.id = id; working_row.ltype1 = res.get_int4(0, 0); working_row.l1 = res.get_int4(0, 1); working_row.ltype2 = res.get_int4(0, 2); working_row.l2 = res.get_int4(0, 3); working_row.pind = res.get_int4(0, 4); working_row.p1 = res.get_int4(0, 5); working_row.p2 = res.get_int4(0, 6); return &working_row; default: error_consistency::throwf("select levtr data query returned %u results", res.rowcount()); } } void PostgreSQLLevTrV6::read_all(std::function dest) { auto res = conn.exec("SELECT id, ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr"); for (unsigned row = 0; row < res.rowcount(); ++row) { working_row.id = res.get_int4(row, 0); working_row.ltype1 = res.get_int4(row, 1); working_row.l1 = res.get_int4(row, 2); working_row.ltype2 = res.get_int4(row, 3); working_row.l2 = res.get_int4(row, 4); working_row.pind = res.get_int4(row, 5); working_row.p1 = res.get_int4(row, 6); working_row.p2 = res.get_int4(row, 7); dest(working_row); } } void PostgreSQLLevTrV6::dump(FILE* out) { int count = 0; fprintf(out, "dump of table lev_tr:\n"); fprintf(out, " id lev tr\n"); auto res = conn.exec("SELECT id, ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr ORDER BY ID"); for (unsigned row = 0; row < res.rowcount(); ++row) { fprintf(out, " %4d ", res.get_int4(row, 0)); { stringstream str; str << to_level(res, row, 1); fprintf(out, "%-20s ", str.str().c_str()); } { stringstream str; str << to_trange(res, row, 5); fprintf(out, "%-10s\n", str.str().c_str()); } ++count; } fprintf(out, "%d element%s in table lev_tr\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/postgresql/internals.h0000644000175000017500000003311212652630043015717 00000000000000/* * db/sqlite/internals - Implementation infrastructure for the PostgreSQL DB connection * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_POSTGRESQL_INTERNALS_H #define DBALLE_DB_POSTGRESQL_INTERNALS_H #include #include #include #include namespace dballe { namespace db { /** * Report an PostgreSQL error */ struct error_postgresql : public db::error { std::string msg; /** * Copy informations from the ODBC diagnostic record to the dba error * report */ error_postgresql(PGconn* db, const std::string& msg); error_postgresql(PGresult* db, const std::string& msg); error_postgresql(const std::string& dbmsg, const std::string& msg); ~error_postgresql() throw () {} wreport::ErrorCode code() const throw () { return wreport::WR_ERR_ODBC; } virtual const char* what() const throw () { return msg.c_str(); } static void throwf(PGconn* db, const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3); static void throwf(PGresult* db, const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3); }; namespace postgresql { int64_t encode_datetime(const Datetime& arg); int64_t encode_int64_t(int64_t arg); /// Argument list for PQexecParams built at compile time template struct Params { static const int count = sizeof...(ARGS); const char* args[sizeof...(ARGS)]; int lengths[sizeof...(ARGS)]; int formats[sizeof...(ARGS)]; void* local[sizeof...(ARGS)]; Params(const ARGS&... args) { _add(0, args...); } ~Params() { for (auto& i: local) free(i); } Params(const Params&) = delete; Params(const Params&&) = delete; Params& operator=(const Params&) = delete; Params& operator=(const Params&&) = delete; protected: /// Terminating condition for compile-time arg expansion void _add(unsigned pos) { } /// Fill in the argument structures template void _add(unsigned pos, std::nullptr_t arg, const REST&... rest) { local[pos] = nullptr; args[pos] = nullptr; lengths[pos] = 0; formats[pos] = 0; _add(pos + 1, rest...); } /// Fill in the argument structures template void _add(unsigned pos, int32_t arg, const REST&... rest) { local[pos] = malloc(sizeof(int32_t)); *(int32_t*)local[pos] = (int32_t)htonl((uint32_t)arg); args[pos] = (const char*)local[pos]; lengths[pos] = sizeof(int32_t); formats[pos] = 1; _add(pos + 1, rest...); } /// Fill in the argument structures template void _add(unsigned pos, uint64_t arg, const REST&... rest) { local[pos] = malloc(sizeof(int64_t)); *(int64_t*)local[pos] = encode_int64_t(arg); args[pos] = (const char*)local[pos]; lengths[pos] = sizeof(int64_t); formats[pos] = 1; _add(pos + 1, rest...); } /// Fill in the argument structures template void _add(unsigned pos, const char* arg, const REST&... rest) { local[pos] = nullptr; args[pos] = arg; lengths[pos] = 0; formats[pos] = 0; _add(pos + 1, rest...); } /// Fill in the argument structures template void _add(unsigned pos, const std::string& arg, const REST&... rest) { local[pos] = nullptr; args[pos] = arg.data(); lengths[pos] = arg.size(); formats[pos] = 0; _add(pos + 1, rest...); } /// Fill in the argument structures template void _add(unsigned pos, const Datetime& arg, const REST&... rest) { local[pos] = malloc(sizeof(int64_t)); *(int64_t*)local[pos] = encode_datetime(arg); args[pos] = (const char*)local[pos]; lengths[pos] = sizeof(int64_t); formats[pos] = 1; _add(pos + 1, rest...); } }; /// Wrap a PGresult, taking care of its memory management struct Result { PGresult* res; Result() : res(nullptr) {} Result(PGresult* res) : res(res) {} ~Result() { PQclear(res); } /// Implement move Result(Result&& o) : res(o.res) { o.res = nullptr; } Result& operator=(Result&& o) { if (this == &o) return *this; PQclear(res); res = o.res; o.res = nullptr; return *this; } operator bool() const { return res != nullptr; } operator PGresult*() { return res; } operator const PGresult*() const { return res; } /// Check that the result successfully returned no data void expect_no_data(const std::string& query); /// Check that the result successfully returned some (possibly empty) data void expect_result(const std::string& query); /// Check that the result successfully returned one row of data void expect_one_row(const std::string& query); /// Check that the result was successful void expect_success(const std::string& query); /// Get the number of rows in the result unsigned rowcount() const { return PQntuples(res); } /// Check if a result value is null bool is_null(unsigned row, unsigned col) const { return PQgetisnull(res, row, col); } /// Return a result value, transmitted in binary as a byte (?) bool get_bool(unsigned row, unsigned col) const { char* val = PQgetvalue(res, row, col); return *val; } /// Return a result value, transmitted in binary as a 2 bit integer uint16_t get_int2(unsigned row, unsigned col) const { char* val = PQgetvalue(res, row, col); return ntohs(*(uint16_t*)val); } /// Return a result value, transmitted in binary as a 4 bit integer uint32_t get_int4(unsigned row, unsigned col) const { char* val = PQgetvalue(res, row, col); return ntohl(*(uint32_t*)val); } /// Return a result value, transmitted in binary as an 8 bit integer uint64_t get_int8(unsigned row, unsigned col) const; /// Return a result value, transmitted as a string const char* get_string(unsigned row, unsigned col) const { return PQgetvalue(res, row, col); } /// Return a result value, transmitted as a timestamp without timezone Datetime get_timestamp(unsigned row, unsigned col) const; // Prevent copy Result(const Result&) = delete; Result& operator=(const Result&) = delete; }; } /// Database connection class PostgreSQLConnection : public Connection { protected: /// Database connection PGconn* db = nullptr; protected: void init_after_connect(); public: PostgreSQLConnection(); PostgreSQLConnection(const PostgreSQLConnection&) = delete; PostgreSQLConnection(const PostgreSQLConnection&&) = delete; ~PostgreSQLConnection(); PostgreSQLConnection& operator=(const PostgreSQLConnection&) = delete; operator PGconn*() { return db; } /** * Connect to PostgreSQL using a connection URI * * The syntax is described at: * http://www.postgresql.org/docs/9.4/static/libpq-connect.html#AEN41094 */ void open_url(const std::string& connection_string); void open_test(); std::unique_ptr transaction() override; /// Precompile a query void prepare(const std::string& name, const std::string& query); postgresql::Result exec_unchecked(const char* query) { return PQexecParams(db, query, 0, nullptr, nullptr, nullptr, nullptr, 1); } postgresql::Result exec_unchecked(const std::string& query) { return PQexecParams(db, query.c_str(), 0, nullptr, nullptr, nullptr, nullptr, 1); } template void exec_no_data(STRING query) { postgresql::Result res(exec_unchecked(query)); res.expect_no_data(query); } template postgresql::Result exec(STRING query) { postgresql::Result res(exec_unchecked(query)); res.expect_result(query); return res; } template postgresql::Result exec_one_row(STRING query) { postgresql::Result res(exec_unchecked(query)); res.expect_one_row(query); return res; } template postgresql::Result exec_unchecked(const char* query, ARGS... args) { postgresql::Params params(args...); return PQexecParams(db, query, params.count, nullptr, params.args, params.lengths, params.formats, 1); } template postgresql::Result exec_unchecked(const std::string& query, ARGS... args) { postgresql::Params params(args...); return PQexecParams(db, query.c_str(), params.count, nullptr, params.args, params.lengths, params.formats, 1); } template void exec_no_data(STRING query, ARGS... args) { postgresql::Result res(exec_unchecked(query, args...)); res.expect_no_data(query); } template postgresql::Result exec(STRING query, ARGS... args) { postgresql::Result res(exec_unchecked(query, args...)); res.expect_result(query); return res; } template postgresql::Result exec_one_row(STRING query, ARGS... args) { postgresql::Result res(exec_unchecked(query, args...)); res.expect_one_row(query); return res; } postgresql::Result exec_prepared_unchecked(const char* name) { return PQexecPrepared(db, name, 0, nullptr, nullptr, nullptr, 1); } postgresql::Result exec_prepared_unchecked(const std::string& name) { return PQexecPrepared(db, name.c_str(), 0, nullptr, nullptr, nullptr, 1); } template void exec_prepared_no_data(STRING name) { postgresql::Result res(exec_prepared_unchecked(name)); res.expect_no_data(name); } template postgresql::Result exec_prepared(STRING name) { postgresql::Result res(exec_prepared_unchecked(name)); res.expect_result(name); return res; } template postgresql::Result exec_prepared_one_row(STRING name) { postgresql::Result res(exec_prepared_unchecked(name)); res.expect_one_row(name); return res; } template postgresql::Result exec_prepared_unchecked(const char* name, ARGS... args) { postgresql::Params params(args...); return PQexecPrepared(db, name, params.count, params.args, params.lengths, params.formats, 1); } template postgresql::Result exec_prepared_unchecked(const std::string& name, ARGS... args) { postgresql::Params params(args...); return PQexecPrepared(db, name.c_str(), params.count, params.args, params.lengths, params.formats, 1); } template void exec_prepared_no_data(STRING name, ARGS... args) { postgresql::Result res(exec_prepared_unchecked(name, args...)); res.expect_no_data(name); } template postgresql::Result exec_prepared(STRING name, ARGS... args) { postgresql::Result res(exec_prepared_unchecked(name, args...)); res.expect_result(name); return res; } template postgresql::Result exec_prepared_one_row(STRING name, ARGS... args) { postgresql::Result res(exec_prepared_unchecked(name, args...)); res.expect_one_row(name); return res; } /// Send a cancellation command to the server void cancel_running_query_nothrow() noexcept; /// Discard all input from an asynchronous request void discard_all_input_nothrow() noexcept; /// Check if the database contains a table bool has_table(const std::string& name) override; /** * Get a value from the settings table. * * Returns the empty string if the table does not exist. */ std::string get_setting(const std::string& key) override; /** * Set a value in the settings table. * * The table is created if it does not exist. */ void set_setting(const std::string& key, const std::string& value) override; /// Drop the settings table void drop_settings() override; /** * Delete a table in the database if it exists, otherwise do nothing. */ void drop_table_if_exists(const char* name); /// Count the number of rows modified by the last query that was run int changes(); /// Wrap PQexec void pqexec(const std::string& query); /** * Wrap PQexec but do not throw an exception in case of errors. * * This is useful to be called in destructors. Errors will be printed to * stderr. */ void pqexec_nothrow(const std::string& query) noexcept; }; } } #endif dballe-7.7/dballe/db/postgresql/driver.h0000644000175000017500000000344712652630043015223 00000000000000/* * db/postgresql/driver - Backend PostgreSQL driver * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_POSTGRESQL_DRIVER_H #define DBALLE_DB_POSTGRESQL_DRIVER_H #include namespace dballe { namespace db { struct PostgreSQLConnection; namespace postgresql { struct Driver : public sql::Driver { PostgreSQLConnection& conn; Driver(PostgreSQLConnection& conn); virtual ~Driver(); std::unique_ptr create_repinfov6() override; std::unique_ptr create_stationv6() override; std::unique_ptr create_levtrv6() override; std::unique_ptr create_datav6() override; std::unique_ptr create_attrv6() override; void run_built_query_v6(const v6::QueryBuilder& qb, std::function dest) override; void create_tables_v6() override; void delete_tables_v6() override; void vacuum_v6() override; void exec_no_data(const std::string& query) override; void explain(const std::string& query) override; }; } } } #endif dballe-7.7/dballe/db/postgresql/station.cc0000644000175000017500000001252012652630043015537 00000000000000#include "station.h" #include "dballe/db/postgresql/internals.h" #include "dballe/core/var.h" #include "dballe/record.h" #include using namespace wreport; using namespace dballe::db; using namespace std; namespace dballe { namespace db { namespace postgresql { StationBase::StationBase(PostgreSQLConnection& conn) : conn(conn) { // Precompile our statements conn.prepare("v6_station_select_fixed", "SELECT id FROM station WHERE lat=$1::int4 AND lon=$2::int4 AND ident IS NULL"); conn.prepare("v6_station_select_mobile", "SELECT id FROM station WHERE lat=$1::int4 AND lon=$2::int4 AND ident=$3::text"); conn.prepare("v6_station_insert", "INSERT INTO station (id, lat, lon, ident) VALUES (DEFAULT, $1::int4, $2::int4, $3::text) RETURNING id"); } StationBase::~StationBase() { } bool StationBase::maybe_get_id(int lat, int lon, const char* ident, int* id) { using namespace postgresql; Result res; if (ident) res = move(conn.exec_prepared("v6_station_select_mobile", lat, lon, ident)); else res = move(conn.exec_prepared("v6_station_select_fixed", lat, lon)); unsigned rows = res.rowcount(); switch (rows) { case 0: return false; case 1: *id = res.get_int4(0, 0); return true; default: error_consistency::throwf("select station ID query returned %u results", rows); } } int StationBase::get_id(int lat, int lon, const char* ident) { int id; if (maybe_get_id(lat, lon, ident, &id)) return id; throw error_notfound("station not found in the database"); } int StationBase::obtain_id(int lat, int lon, const char* ident, bool* inserted) { // TODO: lock table using namespace postgresql; int id; if (maybe_get_id(lat, lon, ident, &id)) { if (inserted) *inserted = false; return id; } // If no station was found, insert a new one Result res(conn.exec_prepared_one_row("v6_station_insert", lat, lon, ident)); if (inserted) *inserted = true; return res.get_int4(0, 0); } void StationBase::get_station_vars(int id_station, int id_report, std::function)> dest) { // Perform the query using namespace postgresql; TRACE("fill_ana_layer Performing query: %s with idst %d idrep %d\n", query, id_station, id_report); Result res(conn.exec_prepared("v6_station_get_station_vars", id_station, id_report)); // Retrieve results Varcode last_varcode = 0; unique_ptr var; for (unsigned row = 0; row < res.rowcount(); ++row) { Varcode code = res.get_int4(row, 0); TRACE("fill_ana_layer Got B%02ld%03ld %s\n", WR_VAR_X(code), WR_VAR_Y(code), out_value); // First process the variable, possibly inserting the old one in the message if (last_varcode != code) { TRACE("fill_ana_layer new var\n"); if (var.get()) { TRACE("fill_ana_layer inserting old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } var = newvar(code, res.get_string(row, 1)); last_varcode = code; } if (!res.is_null(row, 2)) { TRACE("fill_ana_layer new attribute\n"); var->seta(newvar(res.get_int4(row, 2), res.get_string(row, 3))); } }; if (var.get()) { TRACE("fill_ana_layer inserting leftover old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } } void StationBase::add_station_vars(int id_station, Record& rec) { using namespace postgresql; Result res(conn.exec_prepared("v6_station_add_station_vars", id_station)); for (unsigned row = 0; row < res.rowcount(); ++row) rec.set(newvar((Varcode)res.get_int4(row, 0), res.get_string(row, 1))); } void StationBase::dump(FILE* out) { int count = 0; fprintf(out, "dump of table station:\n"); auto res = conn.exec("SELECT id, lat, lon, ident FROM station"); for (unsigned row = 0; row < res.rowcount(); ++row) { fprintf(out, " %d, %.5f, %.5f", res.get_int4(row, 0), res.get_int4(row, 1) / 100000.0, res.get_int4(row, 2) / 100000.0); if (res.is_null(row, 3)) putc('\n', out); else fprintf(out, ", %s\n", res.get_string(row, 3)); ++count; } fprintf(out, "%d element%s in table station\n", count, count != 1 ? "s" : ""); } PostgreSQLStationV6::PostgreSQLStationV6(PostgreSQLConnection& conn) : StationBase(conn) { conn.prepare("v6_station_get_station_vars", R"( SELECT d.id_var, d.value, a.type, a.value FROM data d LEFT JOIN attr a ON a.id_data = d.id WHERE d.id_station=$1::int4 AND d.id_report=$2::int4 AND d.id_lev_tr = -1 ORDER BY d.id_var, a.type )"); conn.prepare("v6_station_add_station_vars", R"( SELECT d.id_var, d.value FROM data d, repinfo ri WHERE d.id_lev_tr = -1 AND ri.id = d.id_report AND d.id_station = $1::int4 AND ri.prio=( SELECT MAX(sri.prio) FROM repinfo sri JOIN data sd ON sri.id=sd.id_report WHERE sd.id_station=d.id_station AND sd.id_lev_tr = -1 AND sd.id_var=d.id_var) )"); } PostgreSQLStationV6::~PostgreSQLStationV6() { } } } } dballe-7.7/dballe/db/postgresql/datav6.cc0000644000175000017500000001527612652630043015256 00000000000000#include "datav6.h" #include "dballe/db/sql.h" #include "dballe/db/v6/qbuilder.h" #include "dballe/record.h" #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace postgresql { PostgreSQLDataV6::PostgreSQLDataV6(PostgreSQLConnection& conn) : conn(conn) { conn.prepare("datav6_insert", R"( INSERT INTO data (id, id_station, id_report, id_lev_tr, datetime, id_var, value) VALUES (DEFAULT, $1::int4, $2::int4, $3::int4, $4::timestamp, $5::int4, $6::text) RETURNING id )"); conn.prepare("datav6_insert_ignore", R"( INSERT INTO data (id_station, id_report, id_lev_tr, datetime, id_var, value) SELECT $1::int4, $2::int4, $3::int4, $4::timestamp, $5::int4, $6::text WHERE NOT EXISTS ( SELECT 1 FROM data WHERE id_station = $1::int4 AND datetime = $4::timestamp AND id_lev_tr = $3::int4 AND id_report = $2::int4 AND id_var = $5::int4 ) RETURNING id )"); conn.prepare("datav6_update", R"( UPDATE data SET value=$2::text WHERE id=$1::int4 )"); conn.prepare("datav6_select_id", R"( SELECT id FROM data WHERE id_station=$1::int4 AND id_report=$2::int4 AND id_lev_tr=$3::int4 AND datetime=$4::timestamp AND id_var=$5::int4 )"); } PostgreSQLDataV6::~PostgreSQLDataV6() { } void PostgreSQLDataV6::insert(Transaction& t, sql::bulk::InsertV6& vars, UpdateMode update_mode) { using namespace postgresql; const char* select_query = R"( SELECT id, id_lev_tr, id_var, value FROM data WHERE id_station=$1::int4 AND id_report=$2::int4 AND datetime=$3::timestamp ORDER BY id_lev_tr, id_var )"; t.lock_table("data"); // Get the current status of variables for this context Result existing(conn.exec(select_query, vars.id_station, vars.id_report, vars.datetime)); // Scan the result in parallel with the variable list, annotating changed // items with their data ID sql::bulk::AnnotateVarsV6 todo(vars); for (unsigned row = 0; row < existing.rowcount(); ++row) { if (!todo.annotate( existing.get_int4(row, 0), existing.get_int4(row, 1), (Varcode)existing.get_int4(row, 2), existing.get_string(row, 3))) break; } todo.annotate_end(); // We now have a todo-list switch (update_mode) { case UPDATE: if (todo.do_update) { Querybuf dq(512); dq.append("UPDATE data as d SET value=i.value FROM (values "); dq.start_list(","); for (auto& v: vars) { if (!v.needs_update()) continue; const char* value = v.var->enqc(); char* escaped_val = PQescapeLiteral(conn, value, strlen(value)); if (!escaped_val) throw error_postgresql(conn, string("escaping string '") + value + "'"); dq.append_listf("(%d, %s)", v.id_data, escaped_val); PQfreemem(escaped_val); v.set_updated(); } dq.append(") AS i(id, value) WHERE d.id = i.id"); //fprintf(stderr, "Update query: %s\n", dq.c_str()); conn.exec_no_data(dq); } break; case IGNORE: break; case ERROR: if (todo.do_update) throw error_consistency("refusing to overwrite existing data"); } if (todo.do_insert) { Querybuf dq(512); dq.append("INSERT INTO data (id, id_station, id_report, id_lev_tr, datetime, id_var, value) VALUES "); dq.start_list(","); for (auto& v: vars) { if (!v.needs_insert()) continue; const char* value = v.var->enqc(); char* escaped_val = PQescapeLiteral(conn, value, strlen(value)); if (!escaped_val) throw error_postgresql(conn, string("escaping string '") + value + "'"); dq.append_listf("(DEFAULT, %d, %d, %d, '%04d-%02d-%02d %02d:%02d:%02d', %d, %s)", vars.id_station, vars.id_report, v.id_levtr, vars.datetime.year, vars.datetime.month, vars.datetime.day, vars.datetime.hour, vars.datetime.minute, vars.datetime.second, (int)v.var->code(), escaped_val); PQfreemem(escaped_val); } dq.append(" RETURNING id"); //fprintf(stderr, "Insert query: %s\n", dq.c_str()); // Run the insert query and read back the new IDs Result res(conn.exec(dq)); unsigned row = 0; auto v = vars.begin(); while (row < res.rowcount() && v != vars.end()) { if (!v->needs_insert()) { ++v; continue; } v->id_data = res.get_int4(row, 0); v->set_inserted(); ++v; ++row; } } } void PostgreSQLDataV6::remove(const v6::QueryBuilder& qb) { Querybuf dq(512); dq.append("DELETE FROM data WHERE id IN ("); dq.append(qb.sql_query); dq.append(")"); if (qb.bind_in_ident) { conn.exec_no_data(dq.c_str(), qb.bind_in_ident); } else { conn.exec_no_data(dq.c_str()); } } void PostgreSQLDataV6::dump(FILE* out) { int count = 0; fprintf(out, "dump of table data:\n"); fprintf(out, " id st rep ltr datetime var\n"); auto res = conn.exec("SELECT id, id_station, id_report, id_lev_tr, datetime, id_var, value FROM data"); for (unsigned row = 0; row < res.rowcount(); ++row) { int id_lev_tr = res.get_int4(row, 3); Datetime datetime = res.get_timestamp(row, 4); Varcode code = res.get_int4(row, 5); char ltr[20]; if (id_lev_tr == -1) strcpy(ltr, "----"); else snprintf(ltr, 20, "%04d", id_lev_tr); stringstream dtstr; dtstr << datetime; fprintf(out, " %4d %4d %3d %s %s %01d%02d%03d", res.get_int4(row, 0), res.get_int4(row, 1), res.get_int4(row, 2), ltr, dtstr.str().c_str(), WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code)); if (res.is_null(row, 6)) fprintf(out, "\n"); else fprintf(out, " %s\n", res.get_string(row, 6)); ++count; }; fprintf(out, "%d element%s in table data\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/postgresql/attrv6.cc0000644000175000017500000001321312652630043015304 00000000000000/* * db/postgresql/attrv6 - attribute table management * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "attrv6.h" #include "dballe/db/sql/internals.h" #include "dballe/db/querybuf.h" #include "dballe/var.h" #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace postgresql { PostgreSQLAttrV6::PostgreSQLAttrV6(PostgreSQLConnection& conn) : conn(conn) { conn.prepare("attrv6_select", R"( SELECT type, value FROM attr WHERE id_data=$1::int4 )"); conn.prepare("attrv6_select_existing", R"( SELECT type, value FROM attr WHERE id_data=$1::int4 )"); conn.prepare("attrv6_insert", R"( INSERT INTO attr (id_data, type, value) VALUES ($1::int4, $2::int4, $3::text) )"); conn.prepare("attrv6_update", R"( UPDATE attr SET value=$3::text WHERE id_data=$1::int4 AND type=$2::int4 )"); } PostgreSQLAttrV6::~PostgreSQLAttrV6() { } void PostgreSQLAttrV6::insert(Transaction& t, sql::bulk::InsertAttrsV6& attrs, UpdateMode update_mode) { Querybuf select_query; select_query.append("SELECT id_data, type, value FROM attr WHERE id_data IN ("); select_query.start_list(","); int last_data_id = -1; for (const auto& a: attrs) { if (a.id_data == last_data_id) continue; select_query.append_listf("%d", a.id_data); last_data_id = a.id_data; } select_query.append(") ORDER BY id_data, type"); t.lock_table("attr"); // Get the current status of attributes for these variables Result res_current(conn.exec(select_query)); sql::bulk::AnnotateAttrsV6 todo(attrs); for (unsigned row = 0; row < res_current.rowcount(); ++row) { todo.annotate( res_current.get_int4(row, 0), res_current.get_int4(row, 1), res_current.get_string(row, 2)); } todo.annotate_end(); // We now have a todo-list switch (update_mode) { case UPDATE: if (todo.do_update) { Querybuf dq(512); dq.append("UPDATE attr as a SET value=i.value FROM (values "); dq.start_list(","); for (auto& a: attrs) { if (!a.needs_update()) continue; const char* value = a.attr->enqc(); char* escaped_val = PQescapeLiteral(conn, value, strlen(value)); if (!escaped_val) throw error_postgresql(conn, string("escaping string '") + value + "'"); dq.append_listf("(%d, %d, %s)", a.id_data, (int)a.attr->code(), escaped_val); PQfreemem(escaped_val); a.set_updated(); } dq.append(") AS i(id_data, type, value) WHERE a.id_data = i.id_data and a.type = i.type"); //fprintf(stderr, "Update query: %s\n", dq.c_str()); conn.exec_no_data(dq); } break; case IGNORE: break; case ERROR: if (todo.do_update) throw error_consistency("refusing to overwrite existing data"); } if (todo.do_insert) { Querybuf dq(512); dq.append("INSERT INTO attr (id_data, type, value) VALUES "); dq.start_list(","); for (auto& a: attrs) { if (!a.needs_insert()) continue; const char* value = a.attr->enqc(); char* escaped_val = PQescapeLiteral(conn, value, strlen(value)); if (!escaped_val) throw error_postgresql(conn, string("escaping string '") + value + "'"); dq.append_listf("(%d, %d, %s)", a.id_data, (int)a.attr->code(), escaped_val); PQfreemem(escaped_val); a.set_inserted(); } //fprintf(stderr, "Insert query: %s\n", dq.c_str()); // Run the insert query and read back the new IDs conn.exec_no_data(dq); } } void PostgreSQLAttrV6::read(int id_data, function)> dest) { using namespace postgresql; Result res = conn.exec_prepared("attrv6_select", id_data); for (unsigned row = 0; row < res.rowcount(); ++row) { if (res.is_null(row, 1)) dest(newvar(res.get_int4(row, 0))); else dest(newvar(res.get_int4(row, 0), res.get_string(row, 1))); } } void PostgreSQLAttrV6::dump(FILE* out) { int count = 0; fprintf(out, "dump of table attr:\n"); auto res = conn.exec("SELECT id_data, type, value FROM attr"); for (unsigned row = 0; row < res.rowcount(); ++row) { Varcode type = res.get_int4(row, 1); const char* val = res.get_string(row, 2); fprintf(out, " %4d, %01d%02d%03d %s", res.get_int4(row, 0), WR_VAR_F(type), WR_VAR_X(type), WR_VAR_Y(type), val); ++count; } fprintf(out, "%d element%s in table attr\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/postgresql/internals.cc0000644000175000017500000002524412652630043016064 00000000000000/* * db/sqlite/internals - Implementation infrastructure for the PostgreSQL DB connection * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "internals.h" #include #include #include #include "dballe/core/vasprintf.h" #include "dballe/db/querybuf.h" #include #include #define _BSD_SOURCE /* See feature_test_macros(7) */ #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace postgresql { // From http://libpqtypes.esilo.com/browse_source.html?file=datetime.c static const int EPOCH_JDATE = 2451545; // == 2000-01-01 int64_t encode_int64_t(int64_t arg) { return htobe64(arg); } int64_t encode_datetime(const Datetime& arg) { int64_t encoded = arg.to_julian() - EPOCH_JDATE; encoded *= 86400; encoded += arg.hour * 3600 + arg.minute * 60 + arg.second; encoded *= 1000000; return (int64_t)htobe64(encoded); } void Result::expect_no_data(const std::string& query) { switch (PQresultStatus(res)) { case PGRES_COMMAND_OK: break; case PGRES_TUPLES_OK: throw error_postgresql("tuples_ok", "data (possibly an empty set) returned by " + query); default: throw error_postgresql(res, "executing " + query); } } void Result::expect_result(const std::string& query) { switch (PQresultStatus(res)) { case PGRES_TUPLES_OK: break; case PGRES_COMMAND_OK: throw error_postgresql("command_ok", "no data returned by " + query); default: throw error_postgresql(res, "executing " + query); } } void Result::expect_one_row(const std::string& query) { switch (PQresultStatus(res)) { case PGRES_TUPLES_OK: break; case PGRES_COMMAND_OK: throw error_postgresql("command_ok", "no data returned by " + query); default: throw error_postgresql(res, "executing " + query); } unsigned rows = rowcount(); if (rows != 1) error_consistency::throwf("Got %u results instead of 1 when running %s", rows, query.c_str()); } void Result::expect_success(const std::string& query) { switch (PQresultStatus(res)) { case PGRES_TUPLES_OK: case PGRES_COMMAND_OK: break; default: throw error_postgresql(res, "executing " + query); } } /// Return a result value, transmitted in binary as a 4 bit integer uint64_t Result::get_int8(unsigned row, unsigned col) const { char* val = PQgetvalue(res, row, col); return be64toh(*(uint64_t*)val); } Datetime Result::get_timestamp(unsigned row, unsigned col) const { // Adapter from http://libpqtypes.esilo.com/browse_source.html?file=datetime.c // Decode from big endian int64_t decoded = be64toh(*(uint64_t*)PQgetvalue(res, row, col)); // Convert from microseconds to seconds decoded = decoded / 1000000; // Split date and time int time = decoded % 86400; int jdate = decoded / 86400; if (time < 0) { time += 86400; jdate -= 1; } // Decode date jdate += EPOCH_JDATE; // Decode time return Datetime::from_julian( jdate, time / 3600, (time / 60) % 60, time % 60); } } error_postgresql::error_postgresql(PGconn* db, const std::string& msg) { this->msg = msg; this->msg += ": "; this->msg += PQerrorMessage(db); } error_postgresql::error_postgresql(PGresult* res, const std::string& msg) { this->msg = msg; this->msg += ": "; this->msg += PQresultErrorMessage(res); } error_postgresql::error_postgresql(const std::string& dbmsg, const std::string& msg) { this->msg = msg; this->msg += ": "; this->msg += dbmsg; } void error_postgresql::throwf(PGconn* db, const char* fmt, ...) { // Format the arguments va_list ap; va_start(ap, fmt); char* cmsg; vasprintf(&cmsg, fmt, ap); va_end(ap); // Convert to string std::string msg(cmsg); free(cmsg); throw error_postgresql(db, msg); } void error_postgresql::throwf(PGresult* res, const char* fmt, ...) { // Format the arguments va_list ap; va_start(ap, fmt); char* cmsg; vasprintf(&cmsg, fmt, ap); va_end(ap); // Convert to string std::string msg(cmsg); free(cmsg); throw error_postgresql(res, msg); } PostgreSQLConnection::PostgreSQLConnection() { } PostgreSQLConnection::~PostgreSQLConnection() { if (db) PQfinish(db); } void PostgreSQLConnection::open_url(const std::string& connection_string) { url = connection_string; db = PQconnectdb(connection_string.c_str()); if (PQstatus(db) != CONNECTION_OK) throw error_postgresql(db, "opening " + connection_string); init_after_connect(); } void PostgreSQLConnection::open_test() { const char* envurl = getenv("DBA_DB_POSTGRESQL"); if (envurl == NULL) throw error_consistency("DBA_DB_POSTGRESQL not defined"); return open_url(envurl); } void PostgreSQLConnection::init_after_connect() { server_type = ServerType::POSTGRES; // Hide warning notices, like "table does not exists" in "DROP TABLE ... IF EXISTS" exec_no_data("SET client_min_messages = error"); } void PostgreSQLConnection::pqexec(const std::string& query) { postgresql::Result res(PQexec(db, query.c_str())); res.expect_success(query); } void PostgreSQLConnection::pqexec_nothrow(const std::string& query) noexcept { postgresql::Result res(PQexec(db, query.c_str())); switch (PQresultStatus(res)) { case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: return; default: fprintf(stderr, "cannot execute '%s': %s\n", query.c_str(), PQresultErrorMessage(res)); } } struct PostgreSQLTransaction : public Transaction { PostgreSQLConnection& conn; bool fired = false; PostgreSQLTransaction(PostgreSQLConnection& conn) : conn(conn) { } ~PostgreSQLTransaction() { if (!fired) rollback_nothrow(); } void commit() override { conn.exec_no_data("COMMIT"); fired = true; } void rollback() override { conn.exec_no_data("ROLLBACK"); fired = true; } void rollback_nothrow() { conn.pqexec_nothrow("ROLLBACK"); fired = true; } void lock_table(const char* name) override { char buf[256]; snprintf(buf, 256, "LOCK TABLE %s IN EXCLUSIVE MODE", name); conn.pqexec(buf); } }; std::unique_ptr PostgreSQLConnection::transaction() { exec_no_data("BEGIN"); return unique_ptr(new PostgreSQLTransaction(*this)); } void PostgreSQLConnection::prepare(const std::string& name, const std::string& query) { using namespace postgresql; Result res(PQprepare(db, name.c_str(), query.c_str(), 0, nullptr)); res.expect_no_data("prepare:" + query); } #if 0 std::unique_ptr PostgreSQLConnection::pqstatement(const std::string& name, const std::string& query) { return unique_ptr(new PostgreSQLCompiledQuery(*this, name, query)); } #endif void PostgreSQLConnection::drop_table_if_exists(const char* name) { exec_no_data(string("DROP TABLE IF EXISTS ") + name); } void PostgreSQLConnection::cancel_running_query_nothrow() noexcept { PGcancel* c = PQgetCancel(db); if (!c) return; char errbuf[256]; if (!PQcancel(c, errbuf, 256)) fprintf(stderr, "cannot send cancellation request: %s\n", errbuf); PQfreeCancel(c); } void PostgreSQLConnection::discard_all_input_nothrow() noexcept { using namespace postgresql; while (true) { Result res(PQgetResult(db)); if (!res) break; switch (PQresultStatus(res)) { case PGRES_TUPLES_OK: break; case PGRES_COMMAND_OK: fprintf(stderr, "flushing input from PostgreSQL server returned an empty result\n"); break; default: fprintf(stderr, "flushing input from PostgreSQL server returned an error: %s\n", PQresultErrorMessage(res)); break; } } } bool PostgreSQLConnection::has_table(const std::string& name) { using namespace postgresql; const char* query = R"( SELECT EXISTS ( SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = 'public' AND c.relname = $1::text ))"; Result res = exec_one_row(query, name); return res.get_bool(0, 0); } std::string PostgreSQLConnection::get_setting(const std::string& key) { using namespace postgresql; if (!has_table("dballe_settings")) return string(); const char* query = "SELECT value FROM dballe_settings WHERE \"key\"=$1::text"; Result res = exec(query, key); if (res.rowcount() == 0) return string(); if (res.rowcount() > 1) error_consistency::throwf("got %d results instead of 1 executing %s", res.rowcount(), query); return res.get_string(0, 0); } void PostgreSQLConnection::set_setting(const std::string& key, const std::string& value) { if (!has_table("dballe_settings")) exec_no_data("CREATE TABLE dballe_settings (\"key\" TEXT NOT NULL PRIMARY KEY, value TEXT NOT NULL)"); auto trans = transaction(); exec_no_data("LOCK TABLE dballe_settings IN EXCLUSIVE MODE"); auto s = exec_one_row("SELECT EXISTS (SELECT 1 FROM dballe_settings WHERE \"key\"=$1::text)", key); if (s.get_bool(0, 0)) exec_no_data("UPDATE dballe_settings SET value=$2::text WHERE \"key\"=$1::text", key, value); else exec_no_data("INSERT INTO dballe_settings (\"key\", value) VALUES ($1::text, $2::text)", key, value); trans->commit(); } void PostgreSQLConnection::drop_settings() { drop_table_if_exists("dballe_settings"); } int PostgreSQLConnection::changes() { throw error_unimplemented("changes"); //return sqlite3_changes(db); } } } dballe-7.7/dballe/db/postgresql/station.h0000644000175000017500000000536112652630043015406 00000000000000/* * db/postgresql/station - station table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_POSTGRESQL_V6_STATION_H #define DBALLE_DB_POSTGRESQL_V6_STATION_H /** @file * @ingroup db * * Station table management used by the db module. */ #include #include #include namespace wreport { struct Var; } namespace dballe { namespace db { struct PostgreSQLConnection; namespace postgresql { struct Result; class StationBase : public sql::Station { protected: /** * DB connection. */ PostgreSQLConnection& conn; /// Lookup the ID of a station, returning true if it was found, false if not bool maybe_get_id(int lat, int lon, const char* ident, int* id); StationBase(const StationBase&) = delete; StationBase(const StationBase&&) = delete; StationBase& operator=(const StationBase&) = delete; public: StationBase(PostgreSQLConnection& conn); ~StationBase(); /** * Get the station ID given latitude, longitude and mobile identifier. * * It throws an exception if it does not exist. * * @return * Resulting ID of the station */ int get_id(int lat, int lon, const char* ident=nullptr) override; /** * Get the station ID given latitude, longitude and mobile identifier. * * It creates the station record if it does not exist. * * @return * Resulting ID of the station */ int obtain_id(int lat, int lon, const char* ident=nullptr, bool* inserted=NULL) override; void get_station_vars(int id_station, int id_report, std::function)> dest) override; void add_station_vars(int id_station, Record& rec) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; class PostgreSQLStationV6 : public postgresql::StationBase { public: PostgreSQLStationV6(PostgreSQLConnection& conn); ~PostgreSQLStationV6(); }; } } } #endif dballe-7.7/dballe/db/postgresql/attrv6.h0000644000175000017500000000404112652630043015145 00000000000000/* * db/postgresql/attrv6 - attribute table management * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_POSTGRESQL_ATTRV6_H #define DBALLE_DB_POSTGRESQL_ATTRV6_H #include #include namespace dballe { namespace db { namespace postgresql { /** * Precompiled queries to manipulate the attr table */ class PostgreSQLAttrV6 : public sql::AttrV6 { protected: /** DB connection. */ PostgreSQLConnection& conn; public: PostgreSQLAttrV6(PostgreSQLConnection& conn); PostgreSQLAttrV6(const PostgreSQLAttrV6&) = delete; PostgreSQLAttrV6(const PostgreSQLAttrV6&&) = delete; PostgreSQLAttrV6& operator=(const PostgreSQLAttrV6&) = delete; ~PostgreSQLAttrV6(); void insert(Transaction& t, sql::bulk::InsertAttrsV6& vars, UpdateMode update_mode=UPDATE) override; /** * Load from the database all the attributes for var * * @param var * wreport::Var to which the resulting attributes will be added * @return * The error indicator for the function (See @ref error.h) */ void read(int id_data, std::function)> dest) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/postgresql/datav6.h0000644000175000017500000000341212652630043015105 00000000000000/* * db/v6/data - data table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_POSTGRESQL_DATAV6_H #define DBALLE_DB_POSTGRESQL_DATAV6_H /** @file * @ingroup db * * Data table management used by the db module. */ #include #include namespace dballe { struct Record; namespace db { namespace postgresql { struct DB; /** * Precompiled query to manipulate the data table */ class PostgreSQLDataV6 : public sql::DataV6 { protected: /** DB connection. */ PostgreSQLConnection& conn; public: PostgreSQLDataV6(PostgreSQLConnection& conn); PostgreSQLDataV6(const PostgreSQLDataV6&) = delete; PostgreSQLDataV6(const PostgreSQLDataV6&&) = delete; PostgreSQLDataV6& operator=(const PostgreSQLDataV6&) = delete; ~PostgreSQLDataV6(); void insert(Transaction& t, sql::bulk::InsertV6& vars, UpdateMode update_mode=UPDATE) override; void remove(const v6::QueryBuilder& qb) override; void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/trace.cc0000644000175000017500000001227012652630043012753 00000000000000/* * dballe/db/trace - Trace and measure DB queries * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "trace.h" #include "dballe/core/query.h" #include #include #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { TraceOp::TraceOp() { } TraceOp::TraceOp(Trace& trace, const char* operation) : trace(&trace), start(clock()) { trace.writer.start_mapping(); add("op", operation); add_list("cmdline", trace.argv); add("pid", trace.pid); add("url", trace.db_url); } TraceOp::~TraceOp() { if (!trace) return; trace->output_abort(); } void TraceOp::done() { if (!trace) return; int elapsed = (clock() - start) * 1000 / CLOCKS_PER_SEC; add("elapsed", elapsed); trace->writer.end_mapping(); trace->output_flush(); } void TraceOp::add_query(const Query& query) { if (!trace) return; trace->writer.add("query"); core::Query::downcast(query).serialize(trace->writer); } Trace::Trace() : writer(json_buf) { const char* outdir = getenv("DBA_LOGDIR"); if (outdir) { read_argv(); pid = getpid(); time_t t = time(NULL); struct tm tmp; localtime_r(&t, &tmp); char buf[20]; strftime(buf, 20, "%Y%m%d-%H%M%S-", &tmp); out_fname = outdir; out_fname += "/"; out_fname += buf; out_fname += to_string(pid); out_fname += ".log"; out = fopen(out_fname.c_str(), "at"); if (!out) error_system::throwf("cannot open file %s", out_fname.c_str()); } } Trace::~Trace() { if (out) fclose(out); } void Trace::read_argv() { FILE* in = fopen("/proc/self/cmdline", "rb"); if (!in) throw error_system("cannot open /proc/self/cmdline"); string cur; char c; while ((c = getc(in)) != EOF) { if (c == 0) { argv.push_back(cur); cur.clear(); } else cur += c; } if (ferror(in)) { int e = errno; fclose(in); throw error_system("cannot read from /proc/self/cmdline", e); } } void Trace::output_abort() { writer.reset(); json_buf.str(""); } void Trace::output_flush() { fputs(json_buf.str().c_str(), out); putc('\n', out); writer.reset(); json_buf.str(""); } Trace::Tracer Trace::trace_connect(const std::string& url) { if (!out) return Tracer(new TraceOp()); db_url = url; return Tracer(new TraceOp(*this, "connect")); } Trace::Tracer Trace::trace_reset(const char* repinfo_file) { if (!out) return Tracer(new TraceOp()); Tracer res(new TraceOp(*this, "reset")); if (repinfo_file) res->add("repinfo", repinfo_file); else res->add_null("repinfo"); return res; } Trace::Tracer Trace::trace_remove_station_data(const Query& query) { if (!out) return Tracer(new TraceOp()); Tracer res(new TraceOp(*this, "remove_station_data")); res->add_query(query); return res; } Trace::Tracer Trace::trace_remove(const Query& query) { if (!out) return Tracer(new TraceOp()); Tracer res(new TraceOp(*this, "remove")); res->add_query(query); return res; } Trace::Tracer Trace::trace_remove_all() { if (!out) return Tracer(new TraceOp()); return Tracer(new TraceOp(*this, "remove_all")); } Trace::Tracer Trace::trace_vacuum() { if (!out) return Tracer(new TraceOp()); return Tracer(new TraceOp(*this, "vacuum")); } Trace::Tracer Trace::trace_query_stations(const Query& query) { if (!out) return Tracer(new TraceOp()); Tracer res(new TraceOp(*this, "query_stations")); res->add_query(query); return res; } Trace::Tracer Trace::trace_query_station_data(const Query& query) { if (!out) return Tracer(new TraceOp()); Tracer res(new TraceOp(*this, "query_station_data")); res->add_query(query); return res; } Trace::Tracer Trace::trace_query_data(const Query& query) { if (!out) return Tracer(new TraceOp()); Tracer res(new TraceOp(*this, "query_data")); res->add_query(query); return res; } Trace::Tracer Trace::trace_query_summary(const Query& query) { if (!out) return Tracer(new TraceOp()); Tracer res(new TraceOp(*this, "query_summary")); res->add_query(query); return res; } Trace::Tracer Trace::trace_export_msgs(const Query& query) { if (!out) return Tracer(new TraceOp()); Tracer res(new TraceOp(*this, "export_msgs")); res->add_query(query); return res; } } } dballe-7.7/dballe/db/summary.cc0000644000175000017500000001056612652630043013360 00000000000000#include "summary.h" #include "dballe/core/query.h" #include "dballe/core/record.h" #include using namespace std; using namespace dballe; namespace dballe { namespace db { namespace summary { Entry::Entry(dballe::db::CursorSummary& cur, bool want_details) { ana_id = cur.get_station_id(); rep_memo = cur.get_rep_memo(); level = cur.get_level(); trange = cur.get_trange(); varcode = cur.get_varcode(); if (want_details) { count = cur.get_count(); dtrange = cur.get_datetimerange(); } } } Summary::Summary(const Query& query) : query(core::Query::downcast(query)) { } summary::Support Summary::supports(const Query& query) const { using namespace summary; // If query is not just a restricted version of our query, then it can // select more data than this summary knows about. if (!query.is_subquery(this->query)) return Support::UNSUPPORTED; // Now we know that query has either more fields than this->query or changes // in datetime or data-related filters Support res = Support::EXACT; const DatetimeRange& new_range = core::Query::downcast(query).datetime; const DatetimeRange& old_range = core::Query::downcast(this->query).datetime; // Check if the query has more restrictive datetime extremes if (old_range != new_range) { if (count == MISSING_INT) { // We do not contain precise datetime information, so we cannot at // this point say anything better than "this summary may // overestimate the query" res = Support::OVERESTIMATED; } else { // The query introduced further restrictions, check with the actual entries what we can do for (const auto& e: summary) { if (new_range.contains(e.dtrange)) ; // If the query entirely contains this summary entry, we can still match it exactly else if (new_range.is_disjoint(e.dtrange)) // If the query is completely outside of this entry, we can still match exactly ; else { // If the query instead only partially overlaps this entry, // we may overestimate the results res = Support::OVERESTIMATED; break; } } } } return res; } void Summary::aggregate(const summary::Entry &val) { all_stations.insert(val.ana_id); all_reports.insert(val.rep_memo); all_levels.insert(val.level); all_tranges.insert(val.trange); all_varcodes.insert(val.varcode); if (val.count != MISSING_INT) { if (count == MISSING_INT) { dtrange = val.dtrange; count = val.count; } else { dtrange.merge(val.dtrange); count += val.count; } } valid = true; } void Summary::add_summary(dballe::db::CursorSummary& cur, bool with_details) { summary.emplace_back(cur, with_details); aggregate(summary.back()); } void Summary::add_entry(const summary::Entry &entry) { summary.push_back(entry); aggregate(summary.back()); } bool Summary::iterate(std::function f) const { for (auto i: summary) if (!f(i)) return false; return true; } namespace summary { Summary& Stack::push(const Query& query) { summaries.emplace_back(query); return summaries.back(); } Support Stack::query(const Query& query, bool exact, std::function match) { if (summaries.empty()) { // If we do not contain any summary, every query is unsupported return Support::UNSUPPORTED; } // Starting from the most specific, drop all summaries that do not support the current query while (summaries.size() > 1) summaries.pop_back(); Support supported = summaries.back().supports(query); if (supported == UNSUPPORTED || (supported == OVERESTIMATED && exact)) return supported; else { int last = summaries.size() - 1; summaries.emplace_back(query); const Summary& source = summaries[last]; source.iterate([&](const Entry& entry) { if (match(entry)) summaries.back().add_entry(entry); return true; }); return supported; } } } } } dballe-7.7/dballe/db/tests.cc0000644000175000017500000003041612652630043013021 00000000000000#include "tests.h" #include "v6/db.h" #include "sql.h" #include "sql/driver.h" #include "dballe/msg/vars.h" #include #include #include #include #include #include "config.h" using namespace wreport; using namespace std; namespace dballe { namespace tests { OverrideTestDBFormat::OverrideTestDBFormat(dballe::db::Format fmt) : old_format(DB::get_default_format()) { DB::set_default_format(fmt); } OverrideTestDBFormat::~OverrideTestDBFormat() { DB::set_default_format(old_format); } Messages messages_from_db(DB& db, const dballe::Query& query) { Messages res; db.export_msgs(query, [&](unique_ptr&& msg) { res.append(move(msg)); return true; }); return res; } Messages messages_from_db(DB& db, const char* query) { Messages res; db.export_msgs(*dballe::tests::query_from_string(query), [&](unique_ptr&& msg) { res.append(move(msg)); return true; }); return res; } #if 0 void StationValues::set_latlonident_into(Record& rec) const { rec.set("lat", lat); rec.set("lon", lon); if (!ident.empty()) rec.set("ident", ident); else rec.unset("ident"); } core::Record TestStation::merged_info_with_highest_prio(DB& db) const { core::Record res; map prios = db.get_repinfo_priorities(); map cur_prios; for (const auto& i: info) { int prio = prios[i.first]; const vector& vars = i.second.vars(); for (vector::const_iterator v = vars.begin(); v != vars.end(); ++v) { map::const_iterator cur_prio = cur_prios.find((*v)->code()); if (cur_prio == cur_prios.end() || cur_prio->second < prio) { res.set(**v); cur_prios[(*v)->code()] = prio; } } } return res; } void TestStation::insert(WIBBLE_TEST_LOCPRM, DB& db, bool can_replace) { for (const auto& i: info) { WIBBLE_TEST_INFO(locinfo); if (i.second.vars().empty()) continue; core::Record insert(i.second); set_latlonident_into(insert); insert.set("rep_memo", i.first); insert.set_datetime(Datetime()); insert.set_level(Level()); insert.set_trange(Trange()); locinfo() << insert.to_string(); wrunchecked(db.insert(insert, can_replace, true)); } } void TestRecord::insert(WIBBLE_TEST_LOCPRM, DB& db, bool can_replace) { // Insert the station info wruntest(station.insert, db, can_replace); ana_id = db.last_station_id(); // Insert variables if (!data.vars().empty()) { WIBBLE_TEST_INFO(locinfo); core::Record insert(data); wrunchecked(station.set_latlonident_into(insert)); locinfo() << insert.to_string(); wrunchecked(db.insert(insert, can_replace, true)); ana_id = db.last_station_id(); } // Insert attributes for (const auto& i: attrs) { WIBBLE_TEST_INFO(locinfo); locinfo() << wreport::varcode_format(i.first) << ": " << i.second.to_string(); wrunchecked(db.attr_insert(i.first, i.second)); } } void TestRecord::set_var(const char* msgvarname, double val, int conf) { int msgvarid = resolve_var(msgvarname); const MsgVarShortcut& v = shortcutTable[msgvarid]; data.set(Level(v.ltype1, v.l1, v.ltype2, v.l2)); data.set(Trange(v.pind, v.p1, v.p2)); data.set(newvar(v.code, val)); if (conf != -1) attrs[v.code].set("B33007", conf); } #endif void ActualCursor::station_keys_match(const Station& expected) { wassert(actual(_actual.get_lat()) == expected.coords.dlat()); wassert(actual(_actual.get_lon()) == expected.coords.dlon()); if (expected.ident.is_missing()) wassert(actual(_actual.get_ident() == nullptr).istrue()); else wassert(actual(_actual.get_ident()) == (const char*)expected.ident); #warning Restore report checks once all DBs return rep_memo for station queries //wassert(actual(cur.get_rep_memo()) == expected.report); } void ActualCursor::station_vars_match(const StationValues& expected) { wassert(actual(_actual).station_keys_match(expected.info)); auto rec = Record::create(); _actual.to_record(*rec); wassert(actual(*rec).vars_equal(expected.values)); } void ActualCursor::data_context_matches(const DataValues& expected) { db::CursorData* c = dynamic_cast(&_actual); if (!c) throw TestFailed("cursor is not an instance of CursorData"); wassert(actual(_actual).station_keys_match(expected.info)); wassert(actual(c->get_rep_memo()) == expected.info.report); wassert(actual(c->get_level()) == expected.info.level); wassert(actual(c->get_trange()) == expected.info.trange); wassert(actual(c->get_datetime()) == expected.info.datetime); auto rec = Record::create(); _actual.to_record(*rec); wassert(actual(rec->enq("rep_memo", "")) == expected.info.report); wassert(actual(rec->enq("leveltype1", MISSING_INT)) == expected.info.level.ltype1); wassert(actual(rec->enq("l1", MISSING_INT)) == expected.info.level.l1); wassert(actual(rec->enq("leveltype2", MISSING_INT)) == expected.info.level.ltype2); wassert(actual(rec->enq("l2", MISSING_INT)) == expected.info.level.l2); wassert(actual(rec->enq("pindicator", MISSING_INT)) == expected.info.trange.pind); wassert(actual(rec->enq("p1", MISSING_INT)) == expected.info.trange.p1); wassert(actual(rec->enq("p2", MISSING_INT)) == expected.info.trange.p2); wassert(actual(rec->enq("year", MISSING_INT)) == expected.info.datetime.year); wassert(actual(rec->enq("month", MISSING_INT)) == expected.info.datetime.month); wassert(actual(rec->enq("day", MISSING_INT)) == expected.info.datetime.day); wassert(actual(rec->enq("hour", MISSING_INT)) == expected.info.datetime.hour); wassert(actual(rec->enq("min", MISSING_INT)) == expected.info.datetime.minute); wassert(actual(rec->enq("sec", MISSING_INT)) == expected.info.datetime.second); } void ActualCursor::data_var_matches(const wreport::Var& expected) { db::CursorValue* c = dynamic_cast(&_actual); if (!c) throw TestFailed("cursor is not an instance of CursorValue"); wassert(actual(c->get_varcode()) == expected.code()); wassert(actual(c->get_var()) == expected); auto rec = Record::create(); wassert(_actual.to_record(*rec)); const Var* actvar = nullptr; for (const auto& i: core::Record::downcast(*rec).vars()) if (i->code() == expected.code()) actvar = i; wassert(actual(actvar).istrue()); wassert(actual(actvar->value_equals(expected)).istrue()); } void ActualCursor::data_matches(const DataValues& ds, wreport::Varcode code) { wassert(actual(_actual).data_context_matches(ds)); wassert(actual(_actual).data_var_matches(ds, code)); } void ActualDB::try_data_query(const std::string& query, unsigned expected) { core::Query q; q.set_from_test_string(query); try_data_query(q, expected); } void ActualDB::try_data_query(const Query& query, unsigned expected) { // Run the query unique_ptr cur = _actual.query_data(query); // Check the number of results wassert(actual(cur->remaining()) == expected); unsigned count = cur->test_iterate(/* stderr */); wassert(actual(count) == expected); } void ActualDB::try_station_query(const std::string& query, unsigned expected) { // Run the query unique_ptr cur = _actual.query_stations(core_query_from_string(query)); // Check the number of results wassert(actual(cur->remaining()) == expected); unsigned count = cur->test_iterate(/* stderr */); wassert(actual(count) == expected); } void ActualDB::try_summary_query(const std::string& query, unsigned expected, result_checker check_results) { // Run the query unique_ptr cur = _actual.query_summary(core_query_from_string(query)); // Check the number of results // query_summary counts results in advance only optionally if (cur->remaining() != 0) wassert(actual(cur->remaining()) == expected); vector results; while (cur->next()) { results.emplace_back(core::Record()); cur->to_record(results.back()); } wassert(actual(results.size()) == expected); if (check_results) { // Sort the records, to make it easier to test results later std::sort(results.begin(), results.end(), [](const core::Record& a, const core::Record& b) { if (int res = a.enq("ana_id", MISSING_INT) - b.enq("ana_id", MISSING_INT)) return res < 0; string sa = a.enq("rep_memo", ""); string sb = b.enq("rep_memo", ""); if (sa < sb) return true; if (sa > sb) return false; Level la = a.get_level(); Level lb = b.get_level(); if (int res = la.compare(lb)) return res < 0; sa = a.enq("var", ""); sb = b.enq("var", ""); if (sa < sb) return true; return false; }); wassert(check_results(results)); } } std::unique_ptr get_test_connection(const std::string& backend) { std::string envname = "DBA_DB"; if (!backend.empty()) { envname = "DBA_DB_"; envname += backend; } const char* envurl = getenv(envname.c_str()); if (envurl == NULL) error_consistency::throwf("Environment variable %s is not set", envname.c_str()); return db::Connection::create_from_url(envurl); } DriverFixture::DriverFixture(const char* backend, db::Format format) : backend(backend ? backend : ""), format(format) { conn = get_test_connection(this->backend).release(); driver = db::sql::Driver::create(*conn).release(); driver->delete_tables(format); driver->create_tables(format); } DriverFixture::~DriverFixture() { if (getenv("PAUSE") == nullptr) driver->delete_tables(format); delete driver; delete conn; } void DriverFixture::test_setup() { Fixture::test_setup(); driver->remove_all(format); } DBFixture::DBFixture(const char* backend, db::Format format) : backend(backend ? backend : ""), format(format) { db = create_db().release(); db->reset(); } DBFixture::~DBFixture() { if (getenv("PAUSE") == nullptr) db->disappear(); delete db; } std::unique_ptr DBFixture::create_db() { if (format == db::MEM) { return DB::connect_memory(); } else { OverrideTestDBFormat odbf(format); auto conn = get_test_connection(backend); return DB::create(move(conn)); } } void DBFixture::test_setup() { Fixture::test_setup(); db->remove_all(); int added, deleted, updated; db->update_repinfo(nullptr, &added, &deleted, &updated); } void DBFixture::populate_database(TestDataSet& data_set) { wassert(data_set.populate_db(*db)); } void TestDataSet::populate_db(DB& db) { for (auto& d: stations) wassert(db.insert_station_data(d.second, true, true)); for (auto& d: data) wassert(db.insert_data(d.second, true, true)); } OldDballeTestDataSet::OldDballeTestDataSet() { stations["synop"].info.report = "synop"; stations["synop"].info.coords = Coords(12.34560, 76.54320); stations["synop"].values.set("B07030", 42); // Height stations["synop"].values.set("B07031", 234); // Heightbaro stations["synop"].values.set("B01001", 1); // Block stations["synop"].values.set("B01002", 52); // Station stations["synop"].values.set("B01019", "Cippo Lippo"); // Name stations["metar"] = stations["synop"]; stations["metar"].info.report = "metar"; data["synop"].info = stations["synop"].info; data["synop"].info.level = Level(10, 11, 15, 22); data["synop"].info.trange = Trange(20, 111, 122); data["synop"].info.datetime = Datetime(1945, 4, 25, 8); data["synop"].values.set("B01011", "DB-All.e!"); data["synop"].values.set("B01012", 300); data["metar"].info = stations["metar"].info; data["metar"].info.level = Level(10, 11, 15, 22); data["metar"].info.trange = Trange(20, 111, 123); data["metar"].info.datetime = Datetime(1945, 4, 25, 8, 30); data["metar"].values.set("B01011", "Arpa-Sim!"); data["metar"].values.set("B01012", 400); } } } dballe-7.7/dballe/db/db-import-test.cc0000644000175000017500000003231712652630043014533 00000000000000#include "config.h" #include "db/tests.h" #include "msg/msg.h" #include "msg/context.h" #include #include using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { unsigned diff_msg(Message& first, Message& second, const char* tag) { notes::Collect c(cerr); int diffs = first.diff(second); if (diffs) dballe::tests::track_different_msgs(first, second, tag); return diffs; } static void normalise_datetime(Msg& msg) { msg::Context* ctx = msg.edit_context(Level(), Trange()); if (!ctx) return; // Strip datetime variables ctx->remove(WR_VAR(0, 4, 1)); ctx->remove(WR_VAR(0, 4, 2)); ctx->remove(WR_VAR(0, 4, 3)); ctx->remove(WR_VAR(0, 4, 4)); ctx->remove(WR_VAR(0, 4, 5)); ctx->remove(WR_VAR(0, 4, 6)); } class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("crex", [](Fixture& f) { auto& db = f.db; core::Query query; // Test import/export with all CREX samples const char** files = dballe::tests::crex_files; set blacklist; // These files have no data to import blacklist.insert("crex/test-synop1.crex"); blacklist.insert("crex/test-synop3.crex"); for (int i = 0; files[i] != NULL; ++i) { if (blacklist.find(files[i]) != blacklist.end()) continue; try { Messages inmsgs = read_msgs(files[i], File::CREX); Msg& msg = Msg::downcast(inmsgs[0]); normalise_datetime(msg); db->remove_all(); db->import_msg(msg, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); // Explicitly set the rep_memo variable that is added during export msg.set_rep_memo(Msg::repmemo_from_type(msg.type)); query.clear(); query.rep_memo = Msg::repmemo_from_type(msg.type); Messages msgs = wcallchecked(dballe::tests::messages_from_db(*db, query)); wassert(actual(msgs.size()) == 1u); wassert(actual(diff_msg(msg, msgs[0], "crex")) == 0); } catch (std::exception& e) { throw TestFailed(string("[") + files[i] + "] " + e.what()); } } }); add_method("bufr", [](Fixture& f) { // Test import/export with all BUFR samples auto& db = f.db; core::Query query; const char** files = dballe::tests::bufr_files; for (int i = 0; files[i] != NULL; i++) { try { Messages inmsgs = read_msgs(files[i], File::BUFR); Msg& msg = Msg::downcast(inmsgs[0]); normalise_datetime(msg); db->remove_all(); wassert(db->import_msg(msg, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA)); query.clear(); query.rep_memo = Msg::repmemo_from_type(msg.type); Messages msgs = dballe::tests::messages_from_db(*db, query); wassert(actual(msgs.size()) == 1u); // Explicitly set the rep_memo variable that is added during export msg.set_rep_memo(Msg::repmemo_from_type(msg.type)); wassert(actual(diff_msg(msg, msgs[0], "bufr")) == 0); } catch (std::exception& e) { throw TestFailed(string("[") + files[i] + "] " + e.what()); } } }); add_method("aof", [](Fixture& f) { // Test import/export with all AOF samples auto& db = f.db; core::Query query; const char** files = dballe::tests::aof_files; for (int i = 0; files[i] != NULL; i++) { try { Messages inmsgs = read_msgs(files[i], File::AOF); Msg& msg = Msg::downcast(inmsgs[0]); normalise_datetime(msg); db->remove_all(); db->import_msg(msg, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); // Explicitly set the rep_memo variable that is added during export msg.set_rep_memo(Msg::repmemo_from_type(msg.type)); // db->dump(stderr); query.clear(); query.rep_memo = Msg::repmemo_from_type(msg.type); Messages msgs = dballe::tests::messages_from_db(*db, query); wassert(actual(msgs.size()) == 1u); wassert(actual(diff_msg(msg, msgs[0], "bufr")) == 0); } catch (std::exception& e) { throw TestFailed(string("[") + files[i] + "] " + e.what()); } } }); add_method("multi", [](Fixture& f) { // Check that multiple messages are correctly identified during export auto& db = f.db; core::Query query; // msg1 has latitude 33.88 // msg2 has latitude 46.22 Messages msgs1 = read_msgs("bufr/obs0-1.22.bufr", File::BUFR); Messages msgs2 = read_msgs("bufr/obs0-3.504.bufr", File::BUFR); Msg& msg1 = Msg::downcast(msgs1[0]); Msg& msg2 = Msg::downcast(msgs2[0]); normalise_datetime(msg1); normalise_datetime(msg2); db->remove_all(); db->import_msg(msg1, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); db->import_msg(msg2, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); // Explicitly set the rep_memo variable that is added during export msg1.set_rep_memo(Msg::repmemo_from_type(msg1.type)); msg2.set_rep_memo(Msg::repmemo_from_type(msg2.type)); query.clear(); query.rep_memo = Msg::repmemo_from_type(msg1.type); // Warning: this test used to fail with older versions of MySQL. // See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=397597 Messages msgs = dballe::tests::messages_from_db(*db, query); wassert(actual(msgs.size()) == 2u); // Compare the two dba_msg wassert(actual(diff_msg(msg1, msgs[0], "synop1")) == 0); wassert(actual(diff_msg(msg2, msgs[1], "synop2")) == 0); }); add_method("auto_repinfo", [](Fixture& f) { // Check automatic repinfo allocation auto& db = f.db; core::Query query; Messages msgs = read_msgs("bufr/generic-new-repmemo.bufr", File::BUFR); Msg& msg = Msg::downcast(msgs[0]); db->remove_all(); db->import_msg(msg, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); query.clear(); query.rep_memo = "enrico"; Messages outmsgs = dballe::tests::messages_from_db(*db, query); wassert(actual(outmsgs.size()) == 1u); // Compare the two dba_msg wassert(actual(diff_msg(msg, outmsgs[0], "enrico")) == 0); }); add_method("station_only", [](Fixture& f) { // Check that a message that only contains station variables does get imported auto& db = f.db; Messages msgs = read_msgs("bufr/generic-onlystation.bufr", File::BUFR); db->remove_all(); db->import_msg(msgs[0], NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); std::unique_ptr cur = db->query_stations(core::Query()); wassert(actual(cur->remaining()) == 1); wassert(actual(cur->next()).istrue()); core::Record result; cur->to_record(result); const std::vector& vars = result.vars(); wassert(actual(vars.size()) == 5); wassert(actual(varcode_format(vars[0]->code())) == "B01019"); wassert(actual(vars[0]->format()) == "My beautifull station"); wassert(actual(varcode_format(vars[1]->code())) == "B01194"); wassert(actual(vars[1]->format()) == "generic"); wassert(actual(varcode_format(vars[2]->code())) == "B05001"); wassert(actual(vars[2]->format()) == "45.00000"); wassert(actual(varcode_format(vars[3]->code())) == "B06001"); wassert(actual(vars[3]->format()) == "10.00000"); wassert(actual(varcode_format(vars[4]->code())) == "B07030"); wassert(actual(vars[4]->format()) == "22.3"); }); add_method("station_only_no_vars", [](Fixture& f) { // Check that a message that only contains station variables does get imported auto& db = f.db; core::Record query; Messages msgs = read_msgs("bufr/arpa-station.bufr", File::BUFR); db->remove_all(); try { db->import_msg(msgs[0], NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); wassert(actual(false).istrue()); } catch (error_notfound& e) { // ok. } // Redo it with manually generated messages, this should not get imported { db->remove_all(); Msg msg; msg.type = MSG_GENERIC; msg.set_rep_memo("synop"); msg.set_latitude(44.53000); msg.set_longitude(11.30000); try { db->import_msg(msg, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); wassert(actual(false).istrue()); } catch (error_notfound& e) { // ok. } } // Same but with a datetime set. This should not get imported, but it // currently does because of a bug. I need to preserve the bug until // the software that relies on it has been migrated to use standard // DB-All.e features. { db->remove_all(); Msg msg; msg.type = MSG_GENERIC; msg.set_rep_memo("synop"); msg.set_latitude(44.53000); msg.set_longitude(11.30000); msg.set_datetime(Datetime(1000, 1, 1, 0, 0, 0)); #warning TODO: fix this test to give an error once we do not need to support this bug anymore //try { db->import_msg(msg, NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA); //wassert(actual(false).istrue()); //} catch (error_notfound& e) { // ok. //} } }); add_method("import_dirty", [](Fixture& f) { // Try importing into a dirty database, no attributes involved auto& db = f.db; core::Record query; auto add_common = [](Msg& msg) { msg.type = MSG_SYNOP; msg.set_rep_memo("synop"); msg.set_latitude(45.4); msg.set_longitude(11.2); msg.set_datetime(Datetime(2015, 4, 25, 12, 30, 45)); }; // Build test messages Msg first; add_common(first); first.set_block(1); // Station variable first.set_station(2); // Station variable first.set_temp_2m(280.1); // Data variable first.set_wet_temp_2m(275.8); // Data variable Msg second; add_common(second); second.set_block(5); // Station variable, different value second.set_station(2); // Station variable, same value second.set_height_station(101.0); // Station variable, new value second.set_temp_2m(281.1); // Data variable, different value second.set_wet_temp_2m(275.8); // Data variable, same value second.set_humidity(55.6); // Data variable, new value // Import the first message db->remove_all(); db->import_msg(first, NULL, DBA_IMPORT_FULL_PSEUDOANA | DBA_IMPORT_OVERWRITE); // Export and check Messages export_first = dballe::tests::messages_from_db(*db, "rep_memo=synop"); wassert(actual(export_first.size()) == 1); wassert(actual(diff_msg(first, export_first[0], "first")) == 0); // Import the second message db->import_msg(second, NULL, DBA_IMPORT_FULL_PSEUDOANA | DBA_IMPORT_OVERWRITE); // Export and check Messages export_second = dballe::tests::messages_from_db(*db, "rep_memo=synop"); wassert(actual(export_second.size()) == 1); wassert(actual(diff_msg(second, export_second[0], "second")) == 0); }); } }; Tests tg1("db_import_mem", nullptr, db::MEM); Tests tg2("db_import_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg4("db_import_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg6("db_import_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg8("db_import_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/odbc/0000755000175000017500000000000012653425050012334 500000000000000dballe-7.7/dballe/db/odbc/internals-test.cc0000644000175000017500000001033012652630043015533 00000000000000#include "db/tests.h" #include "db/odbc/internals.h" #include using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct ConnectorFixture : public Fixture { ODBCConnection conn; ConnectorFixture() { conn.connect_test(); } void test_setup() { Fixture::test_setup(); conn.drop_table_if_exists("dballe_test"); conn.exec("CREATE TABLE dballe_test (val INTEGER NOT NULL)"); } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("query_int", [](Fixture& f) { // Test querying int values auto& c = f.conn; c.exec("INSERT INTO dballe_test VALUES (42)"); auto s = c.odbcstatement("SELECT val FROM dballe_test"); int val = 0; s->bind_out(1, val); s->execute(); unsigned count = 0; while (s->fetch()) ++count; wassert(actual(val) == 42); wassert(actual(count) == 1); }); add_method("query_int_null", [](Fixture& f) { // Test querying int values, with indicators auto& c = f.conn; c.exec("INSERT INTO dballe_test VALUES (42)"); auto s = c.odbcstatement("SELECT val FROM dballe_test"); int val = 0; SQLLEN ind = 0; s->bind_out(1, val, ind); s->execute(); unsigned count = 0; while (s->fetch()) ++count; wassert(actual(val) == 42); wassert(actual(ind) != SQL_NULL_DATA); wassert(actual(count) == 1); }); add_method("query_unsigned", [](Fixture& f) { // Test querying unsigned values auto& c = f.conn; c.exec("INSERT INTO dballe_test VALUES (42)"); auto s = c.odbcstatement("SELECT val FROM dballe_test"); unsigned val = 0; s->bind_out(1, val); s->execute(); unsigned count = 0; while (s->fetch()) ++count; wassert(actual(val) == 42); wassert(actual(count) == 1); }); add_method("query_unsigned_null", [](Fixture& f) { // Test querying unsigned values, with indicators auto& c = f.conn; c.exec("INSERT INTO dballe_test VALUES (42)"); auto s = c.odbcstatement("SELECT val FROM dballe_test"); unsigned val = 0; SQLLEN ind = 0; s->bind_out(1, val, ind); s->execute(); unsigned count = 0; while (s->fetch()) ++count; wassert(actual(val) == 42); wassert(actual(ind) != SQL_NULL_DATA); wassert(actual(count) == 1); }); add_method("query_unsigned_short", [](Fixture& f) { // Test querying unsigned short values auto& c = f.conn; c.exec("INSERT INTO dballe_test VALUES (42)"); auto s = c.odbcstatement("SELECT val FROM dballe_test"); unsigned short val = 0; s->bind_out(1, val); s->execute(); unsigned count = 0; while (s->fetch()) ++count; wassert(actual(val) == 42); wassert(actual(count) == 1); }); add_method("has_tables", [](Fixture& f) { // Test has_tables auto& c = f.conn; wassert(actual(c.has_table("this_should_not_exist")).isfalse()); wassert(actual(c.has_table("dballe_test")).istrue()); }); add_method("settings", [](Fixture& f) { // Test settings auto& c = f.conn; c.drop_table_if_exists("dballe_settings"); wassert(actual(c.has_table("dballe_settings")).isfalse()); wassert(actual(c.get_setting("test_key")) == ""); c.set_setting("test_key", "42"); wassert(actual(c.has_table("dballe_settings")).istrue()); wassert(actual(c.get_setting("test_key")) == "42"); }); } } test("db_internals_odbc"); } dballe-7.7/dballe/db/odbc/repinfo.cc0000644000175000017500000001505012652630043014225 00000000000000/* * db/odbc/repinfo - repinfo table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "repinfo.h" #include "dballe/db/db.h" #include "dballe/db/odbc/internals.h" #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace odbc { ODBCRepinfoBase::ODBCRepinfoBase(ODBCConnection& conn) : Repinfo(conn), conn(conn) { read_cache(); } ODBCRepinfoBase::~ODBCRepinfoBase() { } void ODBCRepinfoBase::read_cache() { auto stm = conn.odbcstatement("SELECT id, memo, description, prio, descriptor, tablea FROM repinfo ORDER BY id"); unsigned id; char memo[20]; SQLLEN memo_ind; char description[255]; SQLLEN description_ind; int prio; char descriptor[6]; SQLLEN descriptor_ind; unsigned tablea; cache.clear(); memo_idx.clear(); stm->bind_out(1, id); stm->bind_out(2, memo, sizeof(memo), memo_ind); stm->bind_out(3, description, sizeof(description), description_ind); stm->bind_out(4, prio); stm->bind_out(5, descriptor, sizeof(descriptor), descriptor_ind); stm->bind_out(6, tablea); stm->execute(); /* Get the results and save them in the record */ while (stm->fetch()) cache_append(id, memo, description, prio, descriptor, tablea); /* Rebuild the memo index as well */ rebuild_memo_idx(); } void ODBCRepinfoBase::insert_auto_entry(const char* memo) { auto stm = conn.odbcstatement("SELECT MAX(id) FROM repinfo"); unsigned id; stm->bind_out(1, id); stm->execute(); stm->fetch_expecting_one(); stm = conn.odbcstatement("SELECT MAX(prio) FROM repinfo"); unsigned prio; stm->bind_out(1, prio); stm->execute(); stm->fetch_expecting_one(); ++id; ++prio; stm = conn.odbcstatement(R"( INSERT INTO repinfo (id, memo, description, prio, descriptor, tablea) VALUES (?, ?, ?, ?, '-', 255) )"); stm->bind_in(1, id); stm->bind_in(2, memo); stm->bind_in(3, memo); stm->bind_in(4, prio); stm->execute_ignoring_results(); } #if 0 /* static void commit_cache_item(struct _dba_db_repinfo_cache* item) { if (item->memo != NULL) free(item->memo); item->memo = item->new_memo; item->new_memo = NULL; if (item->desc != NULL) free(item->desc); item->desc = item->new_desc; item->new_desc = NULL; if (item->descriptor != NULL) free(item->descriptor); item->descriptor = item->new_descriptor; item->new_descriptor = NULL; } */ #endif int ODBCRepinfoBase::id_use_count(unsigned id, const char* name) { unsigned dbid = id; unsigned count; auto stm = conn.odbcstatement("SELECT COUNT(1) FROM context WHERE id_report = ?"); stm->bind_in(1, dbid); stm->bind_out(1, count); stm->execute(); if (!stm->fetch_expecting_one()) error_consistency::throwf("%s is in cache but not in the database (database externally modified?)", name); return count; } void ODBCRepinfoBase::delete_entry(unsigned id) { auto stm = conn.odbcstatement("DELETE FROM repinfo WHERE id=?"); stm->bind_in(1, id); stm->execute_and_close(); } void ODBCRepinfoBase::update_entry(const sql::repinfo::Cache& entry) { auto stm = conn.odbcstatement(R"( UPDATE repinfo set memo=?, description=?, prio=?, descriptor=?, tablea=? WHERE id=? )"); stm->bind_in(1, entry.new_memo.c_str()); stm->bind_in(2, entry.new_desc.c_str()); stm->bind_in(3, entry.new_prio); stm->bind_in(4, entry.new_descriptor.c_str()); stm->bind_in(5, entry.new_tablea); stm->bind_in(6, entry.id); stm->execute_and_close(); } void ODBCRepinfoBase::insert_entry(const sql::repinfo::Cache& entry) { auto stm = conn.odbcstatement(R"( INSERT INTO repinfo (id, memo, description, prio, descriptor, tablea) VALUES (?, ?, ?, ?, ?, ?) )"); stm->bind_in(1, entry.id); stm->bind_in(2, entry.new_memo.c_str()); stm->bind_in(3, entry.new_desc.c_str()); stm->bind_in(4, entry.new_prio); stm->bind_in(5, entry.new_descriptor.c_str()); stm->bind_in(6, entry.new_tablea); stm->execute_and_close(); } void ODBCRepinfoBase::dump(FILE* out) { unsigned id; char memo[20]; SQLLEN memo_ind; char description[255]; SQLLEN description_ind; int prio; char descriptor[6]; SQLLEN descriptor_ind; unsigned tablea; auto stm = conn.odbcstatement("SELECT id, memo, description, prio, descriptor, tablea FROM repinfo ORDER BY id"); stm->bind_out(1, id); stm->bind_out(2, memo, sizeof(memo), memo_ind); stm->bind_out(3, description, sizeof(description), description_ind); stm->bind_out(4, prio); stm->bind_out(5, descriptor, sizeof(descriptor), descriptor_ind); stm->bind_out(6, tablea); stm->execute(); int count; fprintf(out, "dump of table repinfo:\n"); fprintf(out, " id memo description prio desc tablea\n"); for (count = 0; stm->fetch(); ++count) { fprintf(out, " %4d %s %s %d %s %u\n", (int)id, memo_ind == SQL_NULL_DATA ? "-" : memo, description_ind == SQL_NULL_DATA ? "-" : description, (int)prio, descriptor_ind == SQL_NULL_DATA ? "-" : descriptor, (unsigned)tablea ); } fprintf(out, "%d element%s in table repinfo\n", count, count != 1 ? "s" : ""); } ODBCRepinfoV6::ODBCRepinfoV6(ODBCConnection& conn) : ODBCRepinfoBase(conn) {} int ODBCRepinfoV6::id_use_count(unsigned id, const char* name) { unsigned count; auto stm = conn.odbcstatement("SELECT COUNT(1) FROM data WHERE id_report = ?"); stm->bind_in(1, id); stm->bind_out(1, count); stm->execute(); if (!stm->fetch_expecting_one()) error_consistency::throwf("%s is in cache but not in the database (database externally modified?)", name); return count; } } } } dballe-7.7/dballe/db/odbc/levtr.h0000644000175000017500000000560312652630043013564 00000000000000/* * db/odbc/lev_tr - lev_tr table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_ODBC_LEV_TR_H #define DBALLE_DB_ODBC_LEV_TR_H /** @file * @ingroup db * * lev_tr table management used by the db module. */ #include #include #include #include #include namespace dballe { struct Record; struct Msg; namespace msg { struct Context; } namespace db { struct Connection; struct Statement; namespace odbc { struct DB; /** * Precompiled queries to manipulate the lev_tr table */ struct ODBCLevTrV6 : public sql::LevTr { protected: /** * DB connection. */ ODBCConnection& conn; /// lev_tr ID sequence, for databases that need it db::Sequence* seq_lev_tr = nullptr; /** Precompiled select statement */ ODBCStatement* sstm = nullptr; /** Precompiled select data statement */ ODBCStatement* sdstm = nullptr; /** Precompiled insert statement */ ODBCStatement* istm = nullptr; /** Precompiled delete statement */ ODBCStatement* dstm = nullptr; DBRow working_row; /** * Insert a new lev_tr in the database * * @return * The ID of the newly inserted lev_tr */ int insert(); /** * Get the lev_tr id for the current lev_tr data. * * @return * The database ID, or -1 if no existing lev_tr entry matches the given values */ int get_id(); /** * Remove a lev_tr record */ void remove(); public: ODBCLevTrV6(ODBCConnection& conn); ODBCLevTrV6(const LevTr&) = delete; ODBCLevTrV6(const LevTr&&) = delete; ODBCLevTrV6& operator=(const ODBCLevTrV6&) = delete; ~ODBCLevTrV6(); /** * Return the ID for the given Level and Trange, adding it to the database * if it does not already exist */ int obtain_id(const Level& lev, const Trange& tr) override; const DBRow* read(int id) override; void read_all(std::function dest) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/odbc/driver.cc0000644000175000017500000002550512652630043014064 00000000000000/* * db/odbc/driver - Backend ODBC driver * * Copyright (C) 2014--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "driver.h" #include "repinfo.h" #include "station.h" #include "levtr.h" #include "datav6.h" #include "attrv6.h" #include "dballe/db/v6/qbuilder.h" #include #include #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace odbc { Driver::Driver(ODBCConnection& conn) : conn(conn) { } Driver::~Driver() { } std::unique_ptr Driver::create_repinfov6() { return unique_ptr(new ODBCRepinfoV6(conn)); } std::unique_ptr Driver::create_stationv6() { return unique_ptr(new ODBCStationV6(conn)); } std::unique_ptr Driver::create_levtrv6() { return unique_ptr(new ODBCLevTrV6(conn)); } std::unique_ptr Driver::create_datav6() { return unique_ptr(new ODBCDataV6(conn)); } std::unique_ptr Driver::create_attrv6() { return unique_ptr(new ODBCAttrV6(conn)); } void Driver::run_built_query_v6( const v6::QueryBuilder& qb, std::function dest) { auto stm = conn.odbcstatement(qb.sql_query); if (qb.bind_in_ident) stm->bind_in(1, qb.bind_in_ident); sql::SQLRecordV6 rec; int output_seq = 1; SQLLEN out_ident_ind; if (qb.select_station) { stm->bind_out(output_seq++, rec.out_ana_id); stm->bind_out(output_seq++, rec.out_lat); stm->bind_out(output_seq++, rec.out_lon); stm->bind_out(output_seq++, rec.out_ident, sizeof(rec.out_ident), out_ident_ind); } if (qb.select_varinfo) { stm->bind_out(output_seq++, rec.out_rep_cod); stm->bind_out(output_seq++, rec.out_id_ltr); stm->bind_out(output_seq++, rec.out_varcode); } if (qb.select_data_id) stm->bind_out(output_seq++, rec.out_id_data); SQL_TIMESTAMP_STRUCT out_datetime; if (qb.select_data) { stm->bind_out(output_seq++, out_datetime); stm->bind_out(output_seq++, rec.out_value, sizeof(rec.out_value)); } SQL_TIMESTAMP_STRUCT out_datetimemax; if (qb.select_summary_details) { stm->bind_out(output_seq++, rec.out_id_data); stm->bind_out(output_seq++, out_datetime); stm->bind_out(output_seq++, out_datetimemax); } stm->execute(); while (stm->fetch()) { // Apply fixes here to demangle timestamps and NULL indicators if (out_ident_ind == SQL_NULL_DATA) rec.out_ident_size = -1; else rec.out_ident_size = out_ident_ind; rec.out_datetime.year = out_datetime.year; rec.out_datetime.month = out_datetime.month; rec.out_datetime.day = out_datetime.day; rec.out_datetime.hour = out_datetime.hour; rec.out_datetime.minute = out_datetime.minute; rec.out_datetime.second = out_datetime.second; if (qb.select_summary_details) { rec.out_datetimemax.year = out_datetimemax.year; rec.out_datetimemax.month = out_datetimemax.month; rec.out_datetimemax.day = out_datetimemax.day; rec.out_datetimemax.hour = out_datetimemax.hour; rec.out_datetimemax.minute = out_datetimemax.minute; rec.out_datetimemax.second = out_datetimemax.second; } dest(rec); } stm->close_cursor(); } void Driver::create_tables_v6() { switch (conn.server_type) { case ServerType::MYSQL: conn.exec(R"( CREATE TABLE station ( id INTEGER auto_increment PRIMARY KEY, lat INTEGER NOT NULL, lon INTEGER NOT NULL, ident CHAR(64), UNIQUE INDEX(lat, lon, ident(8)), INDEX(lon) ) ENGINE=InnoDB; )"); conn.exec(R"( CREATE TABLE repinfo ( id SMALLINT PRIMARY KEY, memo VARCHAR(20) NOT NULL, description VARCHAR(255) NOT NULL, prio INTEGER NOT NULL, descriptor CHAR(6) NOT NULL, tablea INTEGER NOT NULL, UNIQUE INDEX (prio), UNIQUE INDEX (memo) ) ENGINE=InnoDB; )"); conn.exec(R"( CREATE TABLE lev_tr ( id INTEGER auto_increment PRIMARY KEY, ltype1 INTEGER NOT NULL, l1 INTEGER NOT NULL, ltype2 INTEGER NOT NULL, l2 INTEGER NOT NULL, ptype INTEGER NOT NULL, p1 INTEGER NOT NULL, p2 INTEGER NOT NULL, UNIQUE INDEX (ltype1, l1, ltype2, l2, ptype, p1, p2) ) ENGINE=InnoDB; )"); conn.exec(R"( CREATE TABLE data ( id INTEGER auto_increment PRIMARY KEY, id_station SMALLINT NOT NULL, id_report INTEGER NOT NULL, id_lev_tr INTEGER NOT NULL, datetime DATETIME NOT NULL, id_var SMALLINT NOT NULL, value VARCHAR(255) NOT NULL, UNIQUE INDEX(id_station, datetime, id_lev_tr, id_report, id_var), INDEX(datetime), INDEX(id_lev_tr) ) ENGINE=InnoDB; )"); conn.exec(R"( CREATE TABLE attr ( id_data INTEGER NOT NULL, type SMALLINT NOT NULL, value VARCHAR(255) NOT NULL, UNIQUE INDEX (id_data, type) ) ENGINE=InnoDB; )"); break; case ServerType::ORACLE: conn.exec(R"( CREATE TABLE station ( id INTEGER PRIMARY KEY, lat INTEGER NOT NULL, lon INTEGER NOT NULL, ident VARCHAR2(64), UNIQUE (lat, lon, ident) ); CREATE INDEX pa_lon ON station(lon); CREATE SEQUENCE seq_station; )"); conn.exec(R"( CREATE TABLE repinfo ( id INTEGER PRIMARY KEY, memo VARCHAR2(30) NOT NULL, description VARCHAR2(255) NOT NULL, prio INTEGER NOT NULL, descriptor CHAR(6) NOT NULL, tablea INTEGER NOT NULL, UNIQUE (prio), UNIQUE (memo) ) )"); conn.exec(R"( CREATE TABLE lev_tr ( id INTEGER PRIMARY KEY, ltype1 INTEGER NOT NULL, l1 INTEGER NOT NULL, ltype2 INTEGER NOT NULL, l2 INTEGER NOT NULL, ptype INTEGER NOT NULL, p1 INTEGER NOT NULL, p2 INTEGER NOT NULL, ); CREATE SEQUENCE seq_lev_tr; CREATE UNIQUE INDEX lev_tr_uniq ON lev_tr(ltype1, l1, ltype2, l2, ptype, p1, p2); )"); conn.exec(R"( CREATE TABLE data ( id SERIAL PRIMARY KEY, id_station INTEGER NOT NULL, id_report INTEGER NOT NULL, id_lev_tr INTEGER NOT NULL, datetime DATE NOT NULL, id_var INTEGER NOT NULL, value VARCHAR(255) NOT NULL, ); CREATE UNIQUE INDEX data_uniq(id_station, datetime, id_lev_tr, id_report, id_var); CREATE INDEX data_sta ON data(id_station); CREATE INDEX data_rep ON data(id_report); CREATE INDEX data_dt ON data(datetime); CREATE INDEX data_lt ON data(id_lev_tr); )"); conn.exec(R"( CREATE TABLE attr (" id_data INTEGER NOT NULL, type INTEGER NOT NULL, value VARCHAR(255) NOT NULL, ); CREATE UNIQUE INDEX attr_uniq ON attr(id_data, type); )"); break; default: throw error_unimplemented("ODBC connection is only supported for MySQL and Oracle"); } conn.set_setting("version", "V6"); } void Driver::delete_tables_v6() { conn.drop_sequence_if_exists("seq_lev_tr"); // Oracle only conn.drop_sequence_if_exists("seq_station"); // Oracle only conn.drop_table_if_exists("attr"); conn.drop_table_if_exists("data"); conn.drop_table_if_exists("lev_tr"); conn.drop_table_if_exists("repinfo"); conn.drop_table_if_exists("station"); conn.drop_settings(); } void Driver::vacuum_v6() { switch (conn.server_type) { case ServerType::MYSQL: conn.exec("DELETE c FROM lev_tr c LEFT JOIN data d ON d.id_lev_tr = c.id WHERE d.id_lev_tr IS NULL"); conn.exec("DELETE p FROM station p LEFT JOIN data d ON d.id_station = p.id WHERE d.id IS NULL"); break; default: conn.exec(R"( DELETE FROM lev_tr WHERE id IN ( SELECT ltr.id FROM lev_tr ltr LEFT JOIN data d ON d.id_lev_tr = ltr.id WHERE d.id_lev_tr is NULL) )"); conn.exec(R"( DELETE FROM station WHERE id IN ( SELECT p.id FROM station p LEFT JOIN data d ON d.id_station = p.id WHERE d.id is NULL) )"); break; } } void Driver::exec_no_data(const std::string& query) { conn.exec(query); } } } } dballe-7.7/dballe/db/odbc/repinfo.h0000644000175000017500000000425712652630043014076 00000000000000/* * db/odbc/repinfo - repinfo table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_ODBC_REPINFO_H #define DBALLE_DB_ODBC_REPINFO_H /** @file * @ingroup db * * Repinfo table management used by the db module. */ #include #include #include #include namespace dballe { struct Record; namespace db { struct ODBCConnection; namespace odbc { /** * Fast cached access to the repinfo table */ struct ODBCRepinfoBase : public sql::Repinfo { /** * DB connection. The pointer is assumed always valid during the * lifetime of the object */ ODBCConnection& conn; ODBCRepinfoBase(ODBCConnection& conn); ODBCRepinfoBase(const ODBCRepinfoBase&) = delete; ODBCRepinfoBase(const ODBCRepinfoBase&&) = delete; virtual ~ODBCRepinfoBase(); ODBCRepinfoBase& operator=(const ODBCRepinfoBase&) = delete; void dump(FILE* out) override; protected: int id_use_count(unsigned id, const char* name) override; void delete_entry(unsigned id) override; void update_entry(const sql::repinfo::Cache& entry) override; void insert_entry(const sql::repinfo::Cache& entry) override; void read_cache() override; void insert_auto_entry(const char* memo) override; }; struct ODBCRepinfoV6 : public ODBCRepinfoBase { ODBCRepinfoV6(ODBCConnection& conn); protected: int id_use_count(unsigned id, const char* name) override; }; } } } #endif dballe-7.7/dballe/db/odbc/levtr.cc0000644000175000017500000001263712652630043013727 00000000000000#include "levtr.h" #include "dballe/db/odbc/internals.h" #include "dballe/record.h" #include "dballe/core/defs.h" #include "dballe/msg/msg.h" #include #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace odbc { ODBCLevTrV6::ODBCLevTrV6(ODBCConnection& conn) : conn(conn) { const char* select_query = "SELECT id FROM lev_tr WHERE" " ltype1=? AND l1=? AND ltype2=? AND l2=?" " AND ptype=? AND p1=? AND p2=?"; const char* select_data_query = "SELECT ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr WHERE id=?"; const char* insert_query = "INSERT INTO lev_tr (ltype1, l1, ltype2, l2, ptype, p1, p2) VALUES (?, ?, ?, ?, ?, ?, ?)"; const char* remove_query = "DELETE FROM lev_tr WHERE id=?"; /* Override queries for some databases */ switch (conn.server_type) { case ServerType::ORACLE: insert_query = "INSERT INTO lev_tr VALUES (seq_lev_tr.NextVal, ?, ?, ?, ?, ?, ?, ?)"; seq_lev_tr = new Sequence(conn, "seq_lev_tr"); break; default: break; } /* Create the statement for select fixed */ sstm = conn.odbcstatement(select_query).release(); sstm->bind_in(1, working_row.ltype1); sstm->bind_in(2, working_row.l1); sstm->bind_in(3, working_row.ltype2); sstm->bind_in(4, working_row.l2); sstm->bind_in(5, working_row.pind); sstm->bind_in(6, working_row.p1); sstm->bind_in(7, working_row.p2); sstm->bind_out(1, working_row.id); /* Create the statement for select data */ sdstm = conn.odbcstatement(select_data_query).release(); sdstm->bind_in(1, working_row.id); sdstm->bind_out(1, working_row.ltype1); sdstm->bind_out(2, working_row.l1); sdstm->bind_out(3, working_row.ltype2); sdstm->bind_out(4, working_row.l2); sdstm->bind_out(5, working_row.pind); sdstm->bind_out(6, working_row.p1); sdstm->bind_out(7, working_row.p2); /* Create the statement for insert */ istm = conn.odbcstatement(insert_query).release(); istm->bind_in(1, working_row.ltype1); istm->bind_in(2, working_row.l1); istm->bind_in(3, working_row.ltype2); istm->bind_in(4, working_row.l2); istm->bind_in(5, working_row.pind); istm->bind_in(6, working_row.p1); istm->bind_in(7, working_row.p2); /* Create the statement for remove */ dstm = conn.odbcstatement(remove_query).release(); dstm->bind_in(1, working_row.id); } ODBCLevTrV6::~ODBCLevTrV6() { delete seq_lev_tr; if (sstm) delete sstm; if (sdstm) delete sdstm; if (istm) delete istm; if (dstm) delete dstm; } int ODBCLevTrV6::get_id() { sstm->execute(); /* Get the result */ int res; if (sstm->fetch_expecting_one()) res = working_row.id; else res = -1; return res; } int ODBCLevTrV6::obtain_id(const Level& lev, const Trange& tr) { working_row.ltype1 = lev.ltype1; working_row.l1 = lev.l1; working_row.ltype2 = lev.ltype2; working_row.l2 = lev.l2; working_row.pind = tr.pind; working_row.p1 = tr.p1; working_row.p2 = tr.p2; // Check for an existing lev_tr with these data int id = get_id(); // If there is an existing record, use its ID and don't do an INSERT if (id != -1) return id; return insert(); } int ODBCLevTrV6::insert() { istm->execute_and_close(); if (seq_lev_tr) return seq_lev_tr->read(); else return conn.get_last_insert_id(); } void ODBCLevTrV6::remove() { dstm->execute_and_close(); } const sql::LevTr::DBRow* ODBCLevTrV6::read(int id) { working_row.id = id; sdstm->execute(); if (!sdstm->fetch_expecting_one()) return nullptr; return &working_row; } void ODBCLevTrV6::read_all(std::function dest) { // Prefetch everything auto stm = conn.odbcstatement("SELECT id, ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr"); stm->bind_out(1, working_row.id); stm->bind_out(2, working_row.ltype1); stm->bind_out(3, working_row.l1); stm->bind_out(4, working_row.ltype2); stm->bind_out(5, working_row.l2); stm->bind_out(6, working_row.pind); stm->bind_out(7, working_row.p1); stm->bind_out(8, working_row.p2); stm->execute(); while (stm->fetch()) dest(working_row); } void ODBCLevTrV6::dump(FILE* out) { int id; int ltype1; int l1; int ltype2; int l2; int pind; int p1; int p2; auto stm = conn.odbcstatement("SELECT id, ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr ORDER BY id"); stm->bind_out(1, id); stm->bind_out(2, ltype1); stm->bind_out(3, l1); stm->bind_out(4, ltype2); stm->bind_out(5, l2); stm->bind_out(6, pind); stm->bind_out(7, p1); stm->bind_out(8, p2); stm->execute(); int count; fprintf(out, "dump of table lev_tr:\n"); fprintf(out, " id lev tr\n"); for (count = 0; stm->fetch(); ++count) { fprintf(out, " %4d ", (int)id); { stringstream str; str << Level(ltype1, l1, ltype2, l2); fprintf(out, "%-20s ", str.str().c_str()); } { stringstream str; str << Trange(pind, p1, p2); fprintf(out, "%-10s\n", str.str().c_str()); } } fprintf(out, "%d element%s in table lev_tr\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/odbc/internals.h0000644000175000017500000002066112652630043014430 00000000000000/* * db/odbc/internals - Implementation infrastructure for the ODBC DB connection * * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_ODBC_INTERNALS_H #define DBALLE_DB_ODBC_INTERNALS_H /** @file * @ingroup db * * Database functions and data structures used by the db module, but not * exported as official API. */ #include #include #include #include #include // Bit values for server/driver quirks #define DBA_DB_QUIRK_NO_ROWCOUNT_IN_DIAG (1 << 0) namespace dballe { namespace db { struct ODBCStatement; // Define this to get warnings when a Statement is closed but its data have not // all been read yet // #define DEBUG_WARN_OPEN_TRANSACTIONS /** * Report an ODBC error, using informations from the ODBC diagnostic record */ struct error_odbc : public db::error { std::string msg; /** * Copy informations from the ODBC diagnostic record to the dba error * report */ error_odbc(SQLSMALLINT handleType, SQLHANDLE handle, const std::string& msg); ~error_odbc() throw () {} wreport::ErrorCode code() const throw () { return wreport::WR_ERR_ODBC; } virtual const char* what() const throw () { return msg.c_str(); } static void throwf(SQLSMALLINT handleType, SQLHANDLE handle, const char* fmt, ...) WREPORT_THROWF_ATTRS(3, 4); }; /// ODBC environment struct Environment { SQLHENV od_env; Environment(); ~Environment(); static Environment& get(); private: // disallow copy Environment(const Environment&); Environment& operator=(const Environment&); }; /// Database connection struct ODBCConnection : public Connection { /** ODBC database connection */ SQLHDBC od_conn; /** True if the connection is open */ bool connected; /// Bitfield of quirks we should be aware of when using ODBC unsigned server_quirks; protected: /** Precompiled LAST_INSERT_ID (or equivalent) SQL statement */ ODBCStatement* stm_last_insert_id; /** ID of the last autogenerated primary key */ int m_last_insert_id; public: ODBCConnection(); ODBCConnection(const ODBCConnection&) = delete; ODBCConnection(const ODBCConnection&&) = delete; ~ODBCConnection(); ODBCConnection& operator=(const ODBCConnection&) = delete; void connect(const char* dsn, const char* user, const char* password); void connect_url(const char* url); // void connect_file(const std::string& fname); void connect_test(); void driver_connect(const char* config); std::string driver_name(); std::string driver_version(); void get_info(SQLUSMALLINT info_type, SQLINTEGER& res); void set_autocommit(bool val); void exec(const std::string& query); std::unique_ptr transaction() override; std::unique_ptr odbcstatement(const std::string& query); /// Check if the database contains a table bool has_table(const std::string& name) override; /** * Get a value from the settings table. * * Returns the empty string if the table does not exist. */ std::string get_setting(const std::string& key) override; /** * Set a value in the settings table. * * The table is created if it does not exist. */ void set_setting(const std::string& key, const std::string& value) override; /// Drop the settings table void drop_settings() override; /** * Delete a table in the database if it exists, otherwise do nothing. */ void drop_table_if_exists(const char* name); /** * Delete a sequence in the database if it exists, otherwise do nothing. */ void drop_sequence_if_exists(const char* name); /** * Return LAST_INSERT_ID or LAST_INSER_ROWID or whatever is appropriate for * the current database, if supported. * * If not supported, an exception is thrown. */ int get_last_insert_id(); void add_datetime(Querybuf& qb, const Datetime& dt) const override; protected: void init_after_connect(); }; /// ODBC statement struct ODBCStatement { const ODBCConnection& conn; SQLHSTMT stm = nullptr; /// If non-NULL, ignore all errors with this code const char* ignore_error = nullptr; #ifdef DEBUG_WARN_OPEN_TRANSACTIONS /// Debugging aids: dump query to stderr if destructor is called before fetch returned SQL_NO_DATA std::string debug_query; bool debug_reached_completion = false; #endif ODBCStatement(ODBCConnection& conn); ODBCStatement(const ODBCStatement&) = delete; ODBCStatement(const ODBCStatement&&) = delete; ~ODBCStatement(); ODBCStatement& operator=(const ODBCStatement&) = delete; void bind_in(int idx, const int& val); void bind_in(int idx, const int& val, const SQLLEN& ind); void bind_in(int idx, const unsigned& val); void bind_in(int idx, const unsigned& val, const SQLLEN& ind); void bind_in(int idx, const unsigned short& val); void bind_in(int idx, const unsigned short& val, const SQLLEN& ind); void bind_in(int idx, const char* val); void bind_in(int idx, const char* val, const SQLLEN& ind); void bind_in(int idx, const std::string& val); void bind_in(int idx, const SQL_TIMESTAMP_STRUCT& val); void bind_out(int idx, int& val); void bind_out(int idx, int& val, SQLLEN& ind); void bind_out(int idx, unsigned& val); void bind_out(int idx, unsigned& val, SQLLEN& ind); void bind_out(int idx, unsigned short& val); void bind_out(int idx, unsigned short& val, SQLLEN& ind); void bind_out(int idx, char* val, SQLLEN buflen); void bind_out(int idx, char* val, SQLLEN buflen, SQLLEN& ind); void bind_out(int idx, SQL_TIMESTAMP_STRUCT& val); void bind_out(int idx, SQL_TIMESTAMP_STRUCT& val, SQLLEN& ind); void prepare(const char* query); void prepare(const char* query, int qlen); void prepare(const std::string& query); /// @return SQLExecute's result int execute(); /// @return SQLExecute's result int execute_and_close(); /// @return SQLExecute's result int exec_direct_and_close(const char* query, int qlen); void execute_ignoring_results(); /** * @return the number of columns in the result set (or 0 if the statement * did not return columns) */ int columns_count(); bool fetch(); bool fetch_expecting_one(); void close_cursor(); void close_cursor_if_needed(); /// Row count for select operations size_t select_rowcount(); /// Row count for insert, delete and other non-select operations size_t rowcount(); void set_cursor_forward_only(); void set_cursor_static(); protected: bool error_is_ignored(); bool is_error(int sqlres); }; /// ODBC statement to read a sequence struct Sequence : public ODBCStatement { int out; Sequence(ODBCConnection& conn, const char* name); ~Sequence(); /// Read the current value of the sequence const int& read(); private: // disallow copy Sequence(const Sequence&); Sequence& operator=(const Sequence&); }; static inline bool operator!=(const SQL_TIMESTAMP_STRUCT& a, const SQL_TIMESTAMP_STRUCT& b) { return a.year != b.year || a.month != b.month || a.day != b.day || a.hour != b.hour || a.minute != b.minute || a.second != b.second || a.fraction != b.fraction; } std::ostream& operator<<(std::ostream& o, const SQL_TIMESTAMP_STRUCT& t); static inline SQL_TIMESTAMP_STRUCT make_sql_timestamp(int year, int month, int day, int hour, int minute, int second) { SQL_TIMESTAMP_STRUCT res; res.year = year; res.month = month; res.day = day; res.hour = hour; res.minute = minute; res.second = second; res.fraction = 0; return res; } } // namespace db } // namespace dballe /* vim:set ts=4 sw=4: */ #endif dballe-7.7/dballe/db/odbc/driver.h0000644000175000017500000000330712652630043013722 00000000000000/* * db/odbc/driver - Backend ODBC driver * * Copyright (C) 2014--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_ODBC_DRIVER_H #define DBALLE_DB_ODBC_DRIVER_H #include namespace dballe { namespace db { struct ODBCConnection; namespace odbc { struct Driver : public sql::Driver { ODBCConnection& conn; Driver(ODBCConnection& conn); virtual ~Driver(); std::unique_ptr create_repinfov6() override; std::unique_ptr create_stationv6() override; std::unique_ptr create_levtrv6() override; std::unique_ptr create_datav6() override; std::unique_ptr create_attrv6() override; void run_built_query_v6(const v6::QueryBuilder& qb, std::function dest) override; void create_tables_v6() override; void delete_tables_v6() override; void vacuum_v6() override; void exec_no_data(const std::string& query) override; }; } } } #endif dballe-7.7/dballe/db/odbc/station.cc0000644000175000017500000002707412652630043014255 00000000000000#include "station.h" #include "dballe/db/odbc/internals.h" #include "dballe/core/var.h" #include "dballe/record.h" #include #include #include #include using namespace wreport; using namespace dballe::db; using namespace std; namespace dballe { namespace db { namespace odbc { ODBCStationBase::ODBCStationBase(ODBCConnection& conn) : conn(conn), seq_station(0), sfstm(0), smstm(0), sstm(0), istm(0), ustm(0), dstm(0) { const char* select_fixed_query = "SELECT id FROM station WHERE lat=? AND lon=? AND ident IS NULL"; const char* select_mobile_query = "SELECT id FROM station WHERE lat=? AND lon=? AND ident=?"; const char* select_query = "SELECT lat, lon, ident FROM station WHERE id=?"; const char* insert_query = "INSERT INTO station (lat, lon, ident)" " VALUES (?, ?, ?);"; const char* update_query = "UPDATE station SET lat=?, lon=?, ident=? WHERE id=?"; const char* remove_query = "DELETE FROM station WHERE id=?"; /* Override queries for some databases */ switch (conn.server_type) { case ServerType::ORACLE: seq_station = new db::Sequence(conn, "station_id_seq"); insert_query = "INSERT INTO station (id, lat, lon, ident) VALUES (seq_station.NextVal, ?, ?, ?)"; break; case ServerType::POSTGRES: insert_query = "INSERT INTO station (id, lat, lon, ident) VALUES (nextval(pg_get_serial_sequence('station', 'id')), ?, ?, ?)"; break; default: break; } /* Create the statement for select fixed */ sfstm = conn.odbcstatement(select_fixed_query).release(); sfstm->bind_in(1, lat); sfstm->bind_in(2, lon); sfstm->bind_out(1, id); /* Create the statement for select mobile */ smstm = conn.odbcstatement(select_mobile_query).release(); smstm->bind_in(1, lat); smstm->bind_in(2, lon); smstm->bind_in(3, ident, ident_ind); smstm->bind_out(1, id); /* Create the statement for select station data */ sstm = conn.odbcstatement(select_query).release(); sstm->bind_in(1, id); sstm->bind_out(1, lat); sstm->bind_out(2, lon); sstm->bind_out(3, ident, sizeof(ident), ident_ind); /* Create the statement for insert */ istm = conn.odbcstatement(insert_query).release(); istm->bind_in(1, lat); istm->bind_in(2, lon); istm->bind_in(3, ident, ident_ind); /* Create the statement for update */ ustm = conn.odbcstatement(update_query).release(); ustm->bind_in(1, lat); ustm->bind_in(2, lon); ustm->bind_in(3, ident, ident_ind); ustm->bind_in(4, id); /* Create the statement for remove */ dstm = conn.odbcstatement(remove_query).release(); dstm->bind_in(1, id); } ODBCStationBase::~ODBCStationBase() { if (sfstm) delete sfstm; if (smstm) delete smstm; if (sstm) delete sstm; if (istm) delete istm; if (ustm) delete ustm; if (dstm) delete dstm; if (seq_station) delete seq_station; } void ODBCStationBase::set_ident(const char* val) { if (val) { int len = strlen(val); if (len > 64) len = 64; memcpy(ident, val, len); ident[len] = 0; ident_ind = len; } else { ident[0] = 0; ident_ind = SQL_NULL_DATA; } } int ODBCStationBase::get_id(int lat, int lon, const char* ident) { this->lat = lat; this->lon = lon; set_ident(ident); ODBCStatement* stm = ident_ind == SQL_NULL_DATA ? sfstm : smstm; stm->execute(); if (stm->fetch_expecting_one()) return id; throw error_notfound("station not found in the database"); } void ODBCStationBase::get_data(int qid) { id = qid; sstm->execute(); if (!sstm->fetch_expecting_one()) error_notfound::throwf("looking for information for station id %d", qid); if (ident_ind == SQL_NULL_DATA) ident[0] = 0; } int ODBCStationBase::obtain_id(int lat, int lon, const char* ident, bool* inserted) { this->lat = lat; this->lon = lon; set_ident(ident); // Trying querying ODBCStatement* stm = ident_ind == SQL_NULL_DATA ? sfstm : smstm; stm->execute(); if (stm->fetch_expecting_one()) { if (inserted) *inserted = false; return id; } // If nothing was found, insert it if (inserted) *inserted = true; istm->execute_and_close(); if (seq_station) return seq_station->read(); else return conn.get_last_insert_id(); } void ODBCStationBase::update() { ustm->execute_and_close(); } void ODBCStationBase::remove() { dstm->execute_and_close(); } void ODBCStationBase::get_station_vars(int id_station, int id_report, std::function)> dest) { // Perform the query static const char query[] = "SELECT d.id_var, d.value, a.type, a.value" " FROM context c, data d" " LEFT JOIN attr a ON a.id_context = d.id_context AND a.id_var = d.id_var" " WHERE d.id_context = c.id AND c.id_ana = ? AND c.id_report = ?" " AND c.datetime = {ts '1000-01-01 00:00:00.000'}" " ORDER BY d.id_var, a.type"; auto stm = conn.odbcstatement(query); stm->bind_in(1, id_station); stm->bind_in(2, id_report); Varcode out_varcode; stm->bind_out(1, out_varcode); char out_value[255]; stm->bind_out(2, out_value, sizeof(out_value)); int out_attr_varcode; SQLLEN out_attr_varcode_ind; stm->bind_out(3, out_attr_varcode, out_attr_varcode_ind); char out_attr_value[255]; SQLLEN out_attr_value_ind; stm->bind_out(4, out_attr_value, sizeof(out_attr_value), out_attr_value_ind); TRACE("fill_ana_layer Performing query: %s with idst %d idrep %d\n", query, id_station, id_report); stm->execute(); // Retrieve results Varcode last_varcode = 0; unique_ptr var; while (stm->fetch()) { TRACE("fill_ana_layer Got B%02ld%03ld %s\n", WR_VAR_X(out_varcode), WR_VAR_Y(out_varcode), out_value); // First process the variable, possibly inserting the old one in the message if (last_varcode != out_varcode) { TRACE("fill_ana_layer new var\n"); if (var.get()) { TRACE("fill_ana_layer inserting old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } var = newvar(out_varcode, out_value); last_varcode = out_varcode; } if (out_attr_varcode_ind != -1) { TRACE("fill_ana_layer new attribute\n"); var->seta(newvar(out_attr_varcode, out_attr_value)); } } if (var.get()) { TRACE("fill_ana_layer inserting leftover old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } } void ODBCStationBase::dump(FILE* out) { int id; int lat; int lon; char ident[64]; SQLLEN ident_ind; auto stm = conn.odbcstatement("SELECT id, lat, lon, ident FROM station"); stm->bind_out(1, id); stm->bind_out(2, lat); stm->bind_out(3, lon); stm->bind_out(4, ident, 64, ident_ind); stm->execute(); int count; fprintf(out, "dump of table station:\n"); for (count = 0; stm->fetch(); ++count) if (ident_ind == SQL_NULL_DATA) fprintf(out, " %d, %.5f, %.5f\n", (int)id, lat/100000.0, lon/100000.0); else fprintf(out, " %d, %.5f, %.5f, %.*s\n", (int)id, lat/10000.0, lon/10000.0, (int)ident_ind, ident); fprintf(out, "%d element%s in table station\n", count, count != 1 ? "s" : ""); stm->close_cursor(); } void ODBCStationBase::impl_add_station_vars(const char* query, int id_station, Record& rec) { Varcode last_code = 0; unsigned short st_out_code; char st_out_val[256]; SQLLEN st_out_val_ind; auto stm = conn.odbcstatement(query); stm->bind_in(1, id_station); stm->bind_out(1, st_out_code); stm->bind_out(2, st_out_val, sizeof(st_out_val), st_out_val_ind); stm->execute(); // Get the results and save them in the record while (stm->fetch()) { // If we have already set the value of a variable skip it: since we get // results sorted with descending priority, the first result that we // get is already the higher priority result. if (last_code == st_out_code) continue; last_code = st_out_code; rec.set(newvar((Varcode)st_out_code, st_out_val)); } } void ODBCStationBase::add_station_vars(int id_station, Record& rec) { /* Extra variables to add: * * HEIGHT, B07001 1793 * HEIGHT_BARO, B07031 1823 * ST_NAME, B01019 275 * BLOCK, B01001 257 * STATION, B01002 258 */ const char* query = R"( SELECT d.id_var, d.value FROM context c, data d, repinfo ri WHERE c.id = d.id_context AND ri.id = c.id_report AND c.id_ana = ? AND c.datetime = {ts '1000-01-01 00:00:00.000'} ORDER BY d.id_var, ri.prio DESC )"; impl_add_station_vars(query, id_station, rec); } ODBCStationV6::ODBCStationV6(ODBCConnection& conn) : ODBCStationBase(conn) {} void ODBCStationV6::get_station_vars(int id_station, int id_report, std::function)> dest) { // Perform the query static const char query[] = "SELECT d.id_var, d.value, a.type, a.value" " FROM data d" " LEFT JOIN attr a ON a.id_data = d.id" " WHERE d.id_station = ? AND d.id_report = ?" " AND d.id_lev_tr = -1" " ORDER BY d.id_var, a.type"; auto stm = conn.odbcstatement(query); stm->bind_in(1, id_station); stm->bind_in(2, id_report); Varcode out_varcode; stm->bind_out(1, out_varcode); char out_value[255]; stm->bind_out(2, out_value, sizeof(out_value)); Varcode out_attr_varcode; SQLLEN out_attr_varcode_ind; stm->bind_out(3, out_attr_varcode, out_attr_varcode_ind); char out_attr_value[255]; SQLLEN out_attr_value_ind; stm->bind_out(4, out_attr_value, sizeof(out_attr_value), out_attr_value_ind); TRACE("StationLayerCache::fill Performing query: %s with idst %d idrep %d\n", query, id_station, id_report); stm->execute(); // Retrieve results Varcode last_varcode = 0; unique_ptr var; while (stm->fetch()) { TRACE("StationLayerCache::fill Got B%02ld%03ld %s\n", WR_VAR_X(out_varcode), WR_VAR_Y(out_varcode), out_value); // First process the variable, possibly inserting the old one in the message if (last_varcode != out_varcode) { TRACE("StationLayerCache::fill new var\n"); if (var.get()) { TRACE("StationLayerCache::fill inserting old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } var = newvar(out_varcode, out_value); last_varcode = out_varcode; } if (out_attr_varcode_ind != -1) { TRACE("fill_ana_layer new attribute\n"); var->seta(newvar(out_attr_varcode, out_attr_value)); } } if (var.get()) { TRACE("fill_ana_layer inserting leftover old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } } void ODBCStationV6::add_station_vars(int id_station, Record& rec) { const char* query = R"( SELECT d.id_var, d.value FROM data d, repinfo ri WHERE d.id_lev_tr = -1 AND ri.id = d.id_report AND d.id_station = ? ORDER BY d.id_var, ri.prio DESC )"; impl_add_station_vars(query, id_station, rec); } } } } dballe-7.7/dballe/db/odbc/datav6.cc0000644000175000017500000001254712652630043013760 00000000000000#include "datav6.h" #include "dballe/db/sql.h" #include "dballe/db/v6/qbuilder.h" #include "dballe/record.h" #include #include #include #include using namespace wreport; namespace dballe { namespace db { namespace odbc { ODBCDataV6::ODBCDataV6(ODBCConnection& conn) : conn(conn) { } ODBCDataV6::~ODBCDataV6() { } void ODBCDataV6::insert(Transaction& t, sql::bulk::InsertV6& vars, UpdateMode update_mode) { Querybuf select_query(512); select_query.appendf(R"( SELECT id, id_lev_tr, id_var, value FROM data WHERE id_station=%d AND id_report=%d AND datetime={ts '%04d-%02d-%02d %02d:%02d:%02d'} ORDER BY id_lev_tr, id_var )", vars.id_station, vars.id_report, vars.datetime.year, vars.datetime.month, vars.datetime.day, vars.datetime.hour, vars.datetime.minute, vars.datetime.second); // Get the current status of variables for this context auto stm = conn.odbcstatement(select_query); int id_data; int id_levtr; int id_var; char value[255]; stm->bind_out(1, id_data); stm->bind_out(2, id_levtr); stm->bind_out(3, id_var); stm->bind_out(4, value, 255); // Scan the result in parallel with the variable list, annotating changed // items with their data ID sql::bulk::AnnotateVarsV6 todo(vars); stm->execute(); while (stm->fetch()) todo.annotate(id_data, id_levtr, id_var, value); todo.annotate_end(); // We now have a todo-list switch (update_mode) { case UPDATE: if (todo.do_update) { auto update_stm = conn.odbcstatement("UPDATE data SET value=? WHERE id=?"); for (auto& v: vars) { if (!v.needs_update()) continue; update_stm->bind_in(1, v.var->enqc()); update_stm->bind_in(2, v.id_data); update_stm->execute_and_close(); v.set_updated(); } } break; case IGNORE: break; case ERROR: if (todo.do_update) throw error_consistency("refusing to overwrite existing data"); } if (todo.do_insert) { Querybuf dq(512); dq.appendf(R"( INSERT INTO data (id_station, id_report, id_lev_tr, datetime, id_var, value) VALUES (%d, %d, ?, '%04d-%02d-%02d %02d:%02d:%02d', ?, ?) )", vars.id_station, vars.id_report, vars.datetime.year, vars.datetime.month, vars.datetime.day, vars.datetime.hour, vars.datetime.minute, vars.datetime.second); auto insert = conn.odbcstatement(dq); int varcode; insert->bind_in(2, varcode); for (auto& v: vars) { if (!v.needs_insert()) continue; insert->bind_in(1, v.id_levtr); varcode = v.var->code(); insert->bind_in(3, v.var->enqc()); insert->execute(); v.id_data = conn.get_last_insert_id(); v.set_inserted(); } } } void ODBCDataV6::remove(const v6::QueryBuilder& qb) { auto stm = conn.odbcstatement(qb.sql_query); if (qb.bind_in_ident) stm->bind_in(1, qb.bind_in_ident); // Get the list of data to delete int out_id_data; stm->bind_out(1, out_id_data); // Compile the DELETE query for the data auto stmd = conn.odbcstatement("DELETE FROM data WHERE id=?"); stmd->bind_in(1, out_id_data); // Compile the DELETE query for the attributes auto stma = conn.odbcstatement("DELETE FROM attr WHERE id_data=?"); stma->bind_in(1, out_id_data); stm->execute(); // Iterate all the data_id results, deleting the related data and attributes while (stm->fetch()) { stmd->execute_ignoring_results(); stma->execute_ignoring_results(); } } void ODBCDataV6::dump(FILE* out) { int id; int id_station; int id_report; int id_lev_tr; SQL_TIMESTAMP_STRUCT date; wreport::Varcode id_var; char value[255]; SQLLEN value_ind; auto stm = conn.odbcstatement("SELECT id, id_station, id_report, id_lev_tr, datetime, id_var, value FROM data"); stm->bind_out(1, id); stm->bind_out(2, id_station); stm->bind_out(3, id_report); stm->bind_out(4, id_lev_tr); stm->bind_out(5, date); stm->bind_out(6, id_var); stm->bind_out(7, value, 255, value_ind); stm->execute(); int count; fprintf(out, "dump of table data:\n"); fprintf(out, " id st rep ltr datetime var\n"); for (count = 0; stm->fetch(); ++count) { char ltr[20]; if (id_lev_tr == -1) strcpy(ltr, "----"); else snprintf(ltr, 20, "%04d", (int)id_lev_tr); fprintf(out, " %4d %4d %3d %s %04d-%02d-%02d %02d:%02d:%02d.%d %01d%02d%03d", (int)id, (int)id_station, (int)id_report, ltr, (int)date.year, (int)date.month, (int)date.day, (int)date.hour, (int)date.minute, (int)date.second, (int)date.fraction, WR_VAR_F(id_var), WR_VAR_X(id_var), WR_VAR_Y(id_var)); if (value_ind == SQL_NTS) fprintf(out, "\n"); else fprintf(out, " %.*s\n", (int)value_ind, value); } fprintf(out, "%d element%s in table data\n", count, count != 1 ? "s" : ""); stm->close_cursor(); } } } } dballe-7.7/dballe/db/odbc/attrv6.cc0000644000175000017500000001176212652630043014017 00000000000000/* * db/odbc/attrv6 - attribute table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "attrv6.h" #include "dballe/db/sql/internals.h" #include "dballe/var.h" #include #include #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace odbc { ODBCAttrV6::ODBCAttrV6(ODBCConnection& conn) : conn(conn), sstm(0) { // Create the statement for select sstm = conn.odbcstatement("SELECT type, value FROM attr WHERE id_data=?").release(); sstm->bind_in(1, id_data); sstm->bind_out(1, type); sstm->bind_out(2, value, sizeof(value)); } ODBCAttrV6::~ODBCAttrV6() { if (sstm) delete sstm; } void ODBCAttrV6::read(int id_data, function)> dest) { this->id_data = id_data; // Query all attributes for this var in the current context sstm->execute(); // Make variables out of the results and send them to dest while (sstm->fetch()) dest(newvar(type, value)); sstm->close_cursor(); } void ODBCAttrV6::insert(Transaction& t, sql::bulk::InsertAttrsV6& attrs, UpdateMode update_mode) { Querybuf select_query; select_query.append("SELECT id_data, type, value FROM attr WHERE id_data IN ("); select_query.start_list(","); int last_data_id = -1; for (const auto& a: attrs) { if (a.id_data == last_data_id) continue; select_query.append_listf("%d", a.id_data); last_data_id = a.id_data; } select_query.append(") ORDER BY id_data, type"); // Get the current status of variables for this context auto sstm = conn.odbcstatement(select_query); int id_data; int id_var; char value[255]; sstm->bind_out(1, id_data); sstm->bind_out(2, id_var); sstm->bind_out(3, value, 255); // Scan the result in parallel with the variable list, annotating changed // items with their data ID sql::bulk::AnnotateAttrsV6 todo(attrs); sstm->execute(); while (sstm->fetch()) todo.annotate(id_data, id_var, value); todo.annotate_end(); // We now have a todo-list switch (update_mode) { case UPDATE: if (todo.do_update) { auto update_stm = conn.odbcstatement("UPDATE attr SET value=? WHERE id_data=? AND type=?"); wreport::Varcode code; update_stm->bind_in(3, code); for (auto& a: attrs) { if (!a.needs_update()) continue; update_stm->bind_in(1, a.attr->enqc()); update_stm->bind_in(2, a.id_data); code = a.attr->code(); update_stm->execute_and_close(); a.set_updated(); } } break; case IGNORE: break; case ERROR: if (todo.do_update) throw error_consistency("refusing to overwrite existing data"); } if (todo.do_insert) { auto insert = conn.odbcstatement("INSERT INTO attr (id_data, type, value) VALUES (?, ?, ?)"); wreport::Varcode varcode; insert->bind_in(2, varcode); for (auto& a: attrs) { if (!a.needs_insert()) continue; insert->bind_in(1, a.id_data); varcode = a.attr->code(); insert->bind_in(3, a.attr->enqc()); insert->execute_and_close(); a.set_inserted(); } } } void ODBCAttrV6::dump(FILE* out) { int id_data; wreport::Varcode type; char value[255]; SQLLEN value_ind; auto stm = conn.odbcstatement("SELECT id_data, type, value FROM attr"); stm->bind_out(1, id_data); stm->bind_out(2, type); stm->bind_out(3, value, 255, value_ind); stm->execute(); int count; fprintf(out, "dump of table attr:\n"); for (count = 0; stm->fetch(); ++count) { fprintf(out, " %4d, %01d%02d%03d", (int)id_data, WR_VAR_F(type), WR_VAR_X(type), WR_VAR_Y(type)); if (value_ind == SQL_NTS) fprintf(out, "\n"); else fprintf(out, " %.*s\n", (int)value_ind, value); } fprintf(out, "%d element%s in table attr\n", count, count != 1 ? "s" : ""); stm->close_cursor(); } } } } dballe-7.7/dballe/db/odbc/internals.cc0000644000175000017500000007472012652630043014573 00000000000000/* * db/internals - Internal support infrastructure for the DB * * Copyright (C) 2005--2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ /* TODO: * - Can we use bulk inserts? * http://dev.mysql.com/doc/refman/5.0/en/declare-handlers.html * http://dev.mysql.com/doc/refman/5.0/en/cursors.html */ #include "internals.h" #include #include #include #include #include #include #include #include #include #include "dballe/core/vasprintf.h" #include "dballe/core/verbose.h" #include "dballe/db/querybuf.h" #include using namespace std; using namespace wreport; namespace { template SQLSMALLINT get_odbc_integer_type() { error_unimplemented::throwf( "get_odbc_integer_type called on unsupported type signed: %d, size: %u", (int)is_signed, nbits); } template<> SQLSMALLINT get_odbc_integer_type() { return SQL_C_SSHORT; } template<> SQLSMALLINT get_odbc_integer_type() { return SQL_C_USHORT; } template<> SQLSMALLINT get_odbc_integer_type() { return SQL_C_SLONG; } template<> SQLSMALLINT get_odbc_integer_type() { return SQL_C_ULONG; } template<> SQLSMALLINT get_odbc_integer_type() { return SQL_C_SBIGINT; } template<> SQLSMALLINT get_odbc_integer_type() { return SQL_C_UBIGINT; } } namespace dballe { namespace db { error_odbc::error_odbc(SQLSMALLINT handleType, SQLHANDLE handle, const std::string& msg) { static const int strsize = 200; char stat[10], sqlmsg[strsize]; SQLINTEGER err; SQLSMALLINT mlen; SQLGetDiagRec(handleType, handle, 1, (unsigned char*)stat, &err, (unsigned char*)sqlmsg, strsize, &mlen); if (mlen > strsize) mlen = strsize; this->msg = msg; this->msg += ":"; this->msg += stat; this->msg += " "; this->msg += sqlmsg; } void error_odbc::throwf(SQLSMALLINT handleType, SQLHANDLE handle, const char* fmt, ...) { // Format the arguments va_list ap; va_start(ap, fmt); char* cmsg; vasprintf(&cmsg, fmt, ap); va_end(ap); // Convert to string std::string msg(cmsg); free(cmsg); throw error_odbc(handleType, handle, msg); } static void verbose_odbc_error(SQLSMALLINT handleType, SQLHANDLE handle, const std::string& msg) { static const int strsize = 200; char stat[10], sqlmsg[strsize]; SQLINTEGER err; SQLSMALLINT mlen; SQLGetDiagRec(handleType, handle, 1, (unsigned char*)stat, &err, (unsigned char*)sqlmsg, strsize, &mlen); if (mlen > strsize) mlen = strsize; dba_verbose(DBA_VERB_DB_SQL, "%s: %s\n", msg.c_str(), sqlmsg); } Environment::Environment() { // Allocate ODBC environment handle and register version int res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &od_env); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) throw error_odbc(SQL_HANDLE_ENV, od_env, "Allocating main environment handle"); res = SQLSetEnvAttr(od_env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { error_odbc e(SQL_HANDLE_ENV, od_env, "Asking for ODBC version 3"); SQLFreeHandle(SQL_HANDLE_ENV, od_env); throw e; } } Environment::~Environment() { SQLFreeHandle(SQL_HANDLE_ENV, od_env); } Environment& Environment::get() { static Environment* env = NULL; if (!env) env = new Environment; return *env; } ODBCConnection::ODBCConnection() : connected(false), server_quirks(0), stm_last_insert_id(0) { /* Allocate the ODBC connection handle */ Environment& env = Environment::get(); int sqlres = SQLAllocHandle(SQL_HANDLE_DBC, env.od_env, &od_conn); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) throw error_odbc(SQL_HANDLE_DBC, od_conn, "Allocating new connection handle"); } ODBCConnection::~ODBCConnection() { if (stm_last_insert_id) delete stm_last_insert_id; if (connected) { int sqlres = SQLEndTran(SQL_HANDLE_DBC, od_conn, SQL_ROLLBACK); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) verbose_odbc_error(SQL_HANDLE_DBC, od_conn, "Cannot close existing transactions"); sqlres = SQLDisconnect(od_conn); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) verbose_odbc_error(SQL_HANDLE_DBC, od_conn, "Cannot disconnect from database"); } int sqlres = SQLFreeHandle(SQL_HANDLE_DBC, od_conn); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) verbose_odbc_error(SQL_HANDLE_DBC, od_conn, "Cannot free handle"); } void ODBCConnection::connect(const char* dsn, const char* user, const char* password) { url = "odbc://"; url += user; if (password) url += ":****"; url += "@"; url += dsn; /* Connect to the DSN */ int sqlres = SQLConnect(od_conn, (SQLCHAR*)dsn, SQL_NTS, (SQLCHAR*)user, SQL_NTS, (SQLCHAR*)(password == NULL ? "" : password), SQL_NTS); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) error_odbc::throwf(SQL_HANDLE_DBC, od_conn, "Connecting to DSN %s as user %s", dsn, user); init_after_connect(); } void ODBCConnection::connect_url(const char* url) { this->url = url; string buf(url + 7); size_t pos = buf.find('@'); if (pos == string::npos) { return connect(buf.c_str(), "", ""); // odbc://dsn } // Split the string at '@' string userpass = buf.substr(0, pos); string dsn = buf.substr(pos + 1); pos = userpass.find(':'); if (pos == string::npos) { return connect(dsn.c_str(), userpass.c_str(), ""); // odbc://user@dsn } string user = userpass.substr(0, pos); string pass = userpass.substr(pos + 1); connect(dsn.c_str(), user.c_str(), pass.c_str()); // odbc://user:pass@dsn } #if 0 void ODBCConnection::connect_file(const std::string& fname) { // Access sqlite file directly string buf; if (fname[0] != '/') { char cwd[PATH_MAX]; buf = "Driver=SQLite3;Database="; buf += getcwd(cwd, PATH_MAX); buf += "/"; buf += fname; buf += ";"; } else { buf = "Driver=SQLite3;Database="; buf += fname; buf += ";"; } driver_connect(buf.c_str()); } #endif void ODBCConnection::connect_test() { const char* envurl = getenv("DBA_DB_ODBC"); if (envurl == NULL) throw error_consistency("DBA_DB_ODBC not defined"); return connect_url(envurl); } void ODBCConnection::driver_connect(const char* config) { /* Connect to the DSN */ char sdcout[1024]; SQLSMALLINT outlen; int sqlres = SQLDriverConnect(od_conn, NULL, (SQLCHAR*)config, SQL_NTS, (SQLCHAR*)sdcout, 1024, &outlen, SQL_DRIVER_NOPROMPT); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) error_odbc::throwf(SQL_HANDLE_DBC, od_conn, "Connecting to DB using configuration %s", config); init_after_connect(); } void ODBCConnection::init_after_connect() { /* Find out what kind of database we are working with */ string name = driver_name(); if (name.substr(0, 9) == "libmyodbc" || name.substr(0, 6) == "myodbc") { server_type = ServerType::MYSQL; // MariaDB in at least one version returns 0 for rowcount in SQL_DIAG_CURSOR_ROW_COUNT server_quirks = DBA_DB_QUIRK_NO_ROWCOUNT_IN_DIAG; } else if (name.substr(0, 6) == "sqlite") { string version = driver_version(); server_type = ServerType::SQLITE; if (version < "0.99") server_quirks = DBA_DB_QUIRK_NO_ROWCOUNT_IN_DIAG; } else if (name.substr(0, 5) == "SQORA") server_type = ServerType::ORACLE; else if (name.substr(0, 11) == "libpsqlodbc" || name.substr(0, 8) == "psqlodbc") server_type = ServerType::POSTGRES; else { fprintf(stderr, "ODBC driver %s is unsupported: assuming it's similar to Postgres", name.c_str()); server_type = ServerType::POSTGRES; } connected = true; IFTRACE { SQLINTEGER v; get_info(SQL_DYNAMIC_CURSOR_ATTRIBUTES2, v); if (v & SQL_CA2_CRC_EXACT) TRACE("SQL_DYNAMIC_CURSOR_ATTRIBUTES2 SQL_CA2_CRC_EXACT\n"); if (v & SQL_CA2_CRC_APPROXIMATE) TRACE("SQL_DYNAMIC_CURSOR_ATTRIBUTES2 SQL_CA2_CRC_APPROXIMATE\n"); get_info(SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2, v); if (v & SQL_CA2_CRC_EXACT) TRACE("SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2 SQL_CA2_CRC_EXACT\n"); if (v & SQL_CA2_CRC_APPROXIMATE) TRACE("SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2 SQL_CA2_CRC_APPROXIMATE\n"); get_info(SQL_KEYSET_CURSOR_ATTRIBUTES2, v); if (v & SQL_CA2_CRC_EXACT) TRACE("SQL_KEYSET_CURSOR_ATTRIBUTES2, SQL_CA2_CRC_EXACT\n"); if (v & SQL_CA2_CRC_APPROXIMATE) TRACE("SQL_KEYSET_CURSOR_ATTRIBUTES2, SQL_CA2_CRC_APPROXIMATE\n"); get_info(SQL_STATIC_CURSOR_ATTRIBUTES2, v); if (v & SQL_CA2_CRC_EXACT) TRACE("SQL_STATIC_CURSOR_ATTRIBUTES2, SQL_CA2_CRC_EXACT\n"); if (v & SQL_CA2_CRC_APPROXIMATE) TRACE("SQL_STATIC_CURSOR_ATTRIBUTES2, SQL_CA2_CRC_APPROXIMATE\n"); } set_autocommit(false); } std::string ODBCConnection::driver_name() { char drivername[50]; SQLSMALLINT len; int sqlres = SQLGetInfo(od_conn, SQL_DRIVER_NAME, (SQLPOINTER)drivername, 50, &len); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) throw error_odbc(SQL_HANDLE_DBC, od_conn, "Getting ODBC driver name"); return string(drivername, len); } std::string ODBCConnection::driver_version() { char driverver[50]; SQLSMALLINT len; int sqlres = SQLGetInfo(od_conn, SQL_DRIVER_VER, (SQLPOINTER)driverver, 50, &len); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) throw error_odbc(SQL_HANDLE_DBC, od_conn, "Getting ODBC driver version"); return string(driverver, len); } void ODBCConnection::get_info(SQLUSMALLINT info_type, SQLINTEGER& res) { int sqlres = SQLGetInfo(od_conn, info_type, &res, 0, 0); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) throw error_odbc(SQL_HANDLE_DBC, od_conn, "Getting ODBC driver information"); } void ODBCConnection::set_autocommit(bool val) { int sqlres = SQLSetConnectAttr(od_conn, SQL_ATTR_AUTOCOMMIT, (void*)(val ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF), 0); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) error_odbc::throwf(SQL_HANDLE_DBC, od_conn, "%s ODBC autocommit", val ? "Enabling" : "Disabling"); } struct ODBCTransaction : public Transaction { SQLHDBC od_conn; bool fired = false; ODBCTransaction(SQLHDBC conn) : od_conn(conn) {} ~ODBCTransaction() { if (!fired) rollback(); } void commit() override { int sqlres = SQLEndTran(SQL_HANDLE_DBC, od_conn, SQL_COMMIT); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) throw error_odbc(SQL_HANDLE_DBC, od_conn, "Committing a transaction"); fired = true; } void rollback() override { int sqlres = SQLEndTran(SQL_HANDLE_DBC, od_conn, SQL_ROLLBACK); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) throw error_odbc(SQL_HANDLE_DBC, od_conn, "Rolling back a transaction"); fired = true; } void lock_table(const char* name) override { // No idea what to do here: ODBC is now used mostly for Oracle support, // which is being dismissed, or MySQL support, which does not support // table locks inside transactions. } }; std::unique_ptr ODBCConnection::transaction() { return unique_ptr(new ODBCTransaction(od_conn)); } std::unique_ptr ODBCConnection::odbcstatement(const std::string& query) { unique_ptr res(new ODBCStatement(*this)); res->set_cursor_forward_only(); res->prepare(query); return res; } void ODBCConnection::exec(const std::string& query) { ODBCStatement stm(*this); stm.exec_direct_and_close(query.data(), query.size()); } #define DBA_ODBC_MISSING_TABLE_POSTGRES "42P01" #define DBA_ODBC_MISSING_TABLE_MYSQL "42S01" #define DBA_ODBC_MISSING_TABLE_SQLITE "HY000" #define DBA_ODBC_MISSING_TABLE_ORACLE "42S02" void ODBCConnection::drop_table_if_exists(const char* name) { switch (server_type) { case ServerType::MYSQL: case ServerType::POSTGRES: case ServerType::SQLITE: exec(string("DROP TABLE IF EXISTS ") + name); break; case ServerType::ORACLE: { char buf[100]; int len; len = snprintf(buf, 100, "DROP TABLE %s", name); auto stm = odbcstatement(string(buf, len)); stm->ignore_error = DBA_ODBC_MISSING_TABLE_ORACLE; stm->execute_and_close(); break; } } } #define DBA_ODBC_MISSING_SEQUENCE_ORACLE "HY000" #define DBA_ODBC_MISSING_SEQUENCE_POSTGRES "42P01" void ODBCConnection::drop_sequence_if_exists(const char* name) { switch (server_type) { case ServerType::POSTGRES: exec(string("DROP SEQUENCE IF EXISTS ") + name); break; case ServerType::ORACLE: { char buf[100]; int len; len = snprintf(buf, 100, "DROP SEQUENCE %s", name); auto stm = odbcstatement(string(buf, len)); stm->ignore_error = DBA_ODBC_MISSING_SEQUENCE_ORACLE; stm->execute_and_close(); break; } default: break; } } int ODBCConnection::get_last_insert_id() { // Compile the query on demand if (!stm_last_insert_id) { switch (server_type) { case ServerType::MYSQL: stm_last_insert_id = odbcstatement("SELECT LAST_INSERT_ID()").release(); stm_last_insert_id->bind_out(1, m_last_insert_id); break; case ServerType::SQLITE: stm_last_insert_id = odbcstatement("SELECT LAST_INSERT_ROWID()").release(); stm_last_insert_id->bind_out(1, m_last_insert_id); break; case ServerType::POSTGRES: stm_last_insert_id = odbcstatement("SELECT LASTVAL()").release(); stm_last_insert_id->bind_out(1, m_last_insert_id); break; default: throw error_consistency("get_last_insert_id called on a database that does not support it"); } } stm_last_insert_id->execute(); if (!stm_last_insert_id->fetch_expecting_one()) throw error_consistency("no last insert ID value returned from database"); return m_last_insert_id; } bool ODBCConnection::has_table(const std::string& name) { unique_ptr stm; int count; switch (server_type) { case ServerType::MYSQL: stm = odbcstatement("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name=?"); stm->bind_in(1, name.data(), name.size()); stm->bind_out(1, count); break; case ServerType::SQLITE: stm = odbcstatement("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?"); stm->bind_in(1, name.data(), name.size()); stm->bind_out(1, count); break; case ServerType::ORACLE: stm = odbcstatement("SELECT COUNT(*) FROM user_tables WHERE table_name=UPPER(?)"); stm->bind_in(1, name.data(), name.size()); stm->bind_out(1, count); break; case ServerType::POSTGRES: stm = odbcstatement("SELECT COUNT(*) FROM information_schema.tables WHERE table_name=?"); stm->bind_in(1, name.data(), name.size()); stm->bind_out(1, count); break; } stm->execute(); stm->fetch_expecting_one(); return count > 0; } std::string ODBCConnection::get_setting(const std::string& key) { if (!has_table("dballe_settings")) return string(); char result[64]; SQLLEN result_len; unique_ptr stm; if (server_type == ServerType::MYSQL) stm = odbcstatement("SELECT value FROM dballe_settings WHERE `key`=?"); else stm = odbcstatement("SELECT value FROM dballe_settings WHERE \"key\"=?"); stm->bind_in(1, key.data(), key.size()); stm->bind_out(1, result, 64, result_len); stm->execute(); string res; while (stm->fetch()) res = string(result, result_len); // rtrim string size_t n = res.substr(0, 63).find_last_not_of(' '); if (n != string::npos) res.erase(n+1); return res; } void ODBCConnection::set_setting(const std::string& key, const std::string& value) { if (!has_table("dballe_settings")) { if (server_type == ServerType::MYSQL) exec("CREATE TABLE dballe_settings (`key` CHAR(64) NOT NULL PRIMARY KEY, value CHAR(64) NOT NULL)"); else exec("CREATE TABLE dballe_settings (\"key\" CHAR(64) NOT NULL PRIMARY KEY, value CHAR(64) NOT NULL)"); } // Remove if it exists unique_ptr stm; if (server_type == ServerType::MYSQL) stm = odbcstatement("DELETE FROM dballe_settings WHERE `key`=?"); else stm = odbcstatement("DELETE FROM dballe_settings WHERE \"key\"=?"); stm->bind_in(1, key.data(), key.size()); stm->execute_and_close(); // Then insert it if (server_type == ServerType::MYSQL) stm = odbcstatement("INSERT INTO dballe_settings (`key`, value) VALUES (?, ?)"); else stm = odbcstatement("INSERT INTO dballe_settings (\"key\", value) VALUES (?, ?)"); SQLLEN key_size = key.size(); SQLLEN value_size = value.size(); stm->bind_in(1, key.data(), key_size); stm->bind_in(2, value.data(), value_size); stm->execute_and_close(); } void ODBCConnection::drop_settings() { drop_table_if_exists("dballe_settings"); } void ODBCConnection::add_datetime(Querybuf& qb, const Datetime& dt) const { qb.appendf("{ts '%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu'}", dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second); } ODBCStatement::ODBCStatement(ODBCConnection& conn) : conn(conn) { int sqlres = SQLAllocHandle(SQL_HANDLE_STMT, conn.od_conn, &stm); if ((sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO)) throw error_odbc(SQL_HANDLE_STMT, stm, "Allocating new statement handle"); } ODBCStatement::~ODBCStatement() { #ifdef DEBUG_WARN_OPEN_TRANSACTIONS if (!debug_reached_completion) { string msg("Statement " + debug_query + " destroyed before reaching completion"); fprintf(stderr, "-- %s\n", msg.c_str()); //throw error_consistency(msg) SQLCloseCursor(stm); } #endif SQLFreeHandle(SQL_HANDLE_STMT, stm); } bool ODBCStatement::error_is_ignored() { if (!ignore_error) return false; // Retrieve the current error code char stat[10]; SQLINTEGER err; SQLSMALLINT mlen; SQLGetDiagRec(SQL_HANDLE_STMT, stm, 1, (unsigned char*)stat, &err, NULL, 0, &mlen); // Ignore the given SQL error return memcmp(stat, ignore_error, 5) == 0; } bool ODBCStatement::is_error(int sqlres) { return (sqlres != SQL_SUCCESS) && (sqlres != SQL_SUCCESS_WITH_INFO) && (sqlres != SQL_NO_DATA) && !error_is_ignored(); } void ODBCStatement::bind_in(int idx, const int& val) { // cast away const because the ODBC API is not const-aware SQLBindParameter(stm, idx, SQL_PARAM_INPUT, get_odbc_integer_type(), SQL_INTEGER, 0, 0, (int*)&val, 0, 0); } void ODBCStatement::bind_in(int idx, const int& val, const SQLLEN& ind) { // cast away const because the ODBC API is not const-aware SQLBindParameter(stm, idx, SQL_PARAM_INPUT, get_odbc_integer_type(), SQL_INTEGER, 0, 0, (int*)&val, 0, (SQLLEN*)&ind); } void ODBCStatement::bind_in(int idx, const unsigned& val) { // cast away const because the ODBC API is not const-aware SQLBindParameter(stm, idx, SQL_PARAM_INPUT, get_odbc_integer_type(), SQL_INTEGER, 0, 0, (unsigned*)&val, 0, 0); } void ODBCStatement::bind_in(int idx, const unsigned& val, const SQLLEN& ind) { // cast away const because the ODBC API is not const-aware SQLBindParameter(stm, idx, SQL_PARAM_INPUT, get_odbc_integer_type(), SQL_INTEGER, 0, 0, (unsigned*)&val, 0, (SQLLEN*)&ind); } void ODBCStatement::bind_in(int idx, const unsigned short& val) { // cast away const because the ODBC API is not const-aware SQLBindParameter(stm, idx, SQL_PARAM_INPUT, get_odbc_integer_type(), SQL_INTEGER, 0, 0, (unsigned short*)&val, 0, 0); } void ODBCStatement::bind_in(int idx, const unsigned short& val, const SQLLEN& ind) { // cast away const because the ODBC API is not const-aware SQLBindParameter(stm, idx, SQL_PARAM_INPUT, get_odbc_integer_type(), SQL_INTEGER, 0, 0, (unsigned short*)&val, 0, (SQLLEN*)&ind); } void ODBCStatement::bind_in(int idx, const char* val) { // cast away const because the ODBC API is not const-aware SQLBindParameter(stm, idx, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, (char*)val, 0, 0); } void ODBCStatement::bind_in(int idx, const char* val, const SQLLEN& ind) { // cast away const because the ODBC API is not const-aware SQLBindParameter(stm, idx, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, (char*)val, 0, (SQLLEN*)&ind); } void ODBCStatement::bind_in(int idx, const std::string& val) { // cast away const because the ODBC API is not const-aware SQLBindParameter(stm, idx, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, (char*)val.c_str(), 0, nullptr); } void ODBCStatement::bind_in(int idx, const SQL_TIMESTAMP_STRUCT& val) { // cast away const because the ODBC API is not const-aware //if (conn.server_type == POSTGRES || conn.server_type == SQLITE) SQLBindParameter(stm, idx, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TIMESTAMP, 0, 0, (SQL_TIMESTAMP_STRUCT*)&val, 0, 0); //else //SQLBindParameter(stm, idx, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_DATETIME, 0, 0, (SQL_TIMESTAMP_STRUCT*)&val, 0, 0); } void ODBCStatement::bind_out(int idx, int& val) { SQLBindCol(stm, idx, get_odbc_integer_type(), &val, sizeof(val), 0); } void ODBCStatement::bind_out(int idx, int& val, SQLLEN& ind) { SQLBindCol(stm, idx, get_odbc_integer_type(), &val, sizeof(val), &ind); } void ODBCStatement::bind_out(int idx, unsigned& val) { SQLBindCol(stm, idx, get_odbc_integer_type(), &val, sizeof(val), 0); } void ODBCStatement::bind_out(int idx, unsigned& val, SQLLEN& ind) { SQLBindCol(stm, idx, get_odbc_integer_type(), &val, sizeof(val), &ind); } void ODBCStatement::bind_out(int idx, unsigned short& val) { SQLBindCol(stm, idx, SQL_C_USHORT, &val, sizeof(val), 0); } void ODBCStatement::bind_out(int idx, unsigned short& val, SQLLEN& ind) { SQLBindCol(stm, idx, SQL_C_USHORT, &val, sizeof(val), &ind); } void ODBCStatement::bind_out(int idx, char* val, SQLLEN buflen) { SQLBindCol(stm, idx, SQL_C_CHAR, val, buflen, 0); } void ODBCStatement::bind_out(int idx, char* val, SQLLEN buflen, SQLLEN& ind) { SQLBindCol(stm, idx, SQL_C_CHAR, val, buflen, &ind); } void ODBCStatement::bind_out(int idx, SQL_TIMESTAMP_STRUCT& val) { SQLBindCol(stm, idx, SQL_C_TYPE_TIMESTAMP, &val, sizeof(val), 0); } void ODBCStatement::bind_out(int idx, SQL_TIMESTAMP_STRUCT& val, SQLLEN& ind) { SQLBindCol(stm, idx, SQL_C_TYPE_TIMESTAMP, &val, sizeof(val), &ind); } bool ODBCStatement::fetch() { int sqlres = SQLFetch(stm); if (sqlres == SQL_NO_DATA) { #ifdef DEBUG_WARN_OPEN_TRANSACTIONS debug_reached_completion = true; #endif return false; } if (is_error(sqlres)) throw error_odbc(SQL_HANDLE_STMT, stm, "fetching data"); return true; } bool ODBCStatement::fetch_expecting_one() { if (!fetch()) { close_cursor(); return false; } if (fetch()) throw error_consistency("expecting only one result from statement"); close_cursor(); return true; } size_t ODBCStatement::select_rowcount() { if (conn.server_quirks & DBA_DB_QUIRK_NO_ROWCOUNT_IN_DIAG) return rowcount(); SQLLEN res; int sqlres = SQLGetDiagField(SQL_HANDLE_STMT, stm, 0, SQL_DIAG_CURSOR_ROW_COUNT, &res, 0, NULL); // SQLRowCount is broken in newer sqlite odbc //int sqlres = SQLRowCount(stm, &res); if (is_error(sqlres)) throw error_odbc(SQL_HANDLE_STMT, stm, "reading row count"); return res; } size_t ODBCStatement::rowcount() { SQLLEN res; int sqlres = SQLRowCount(stm, &res); if (is_error(sqlres)) throw error_odbc(SQL_HANDLE_STMT, stm, "reading row count"); return res; } void ODBCStatement::set_cursor_forward_only() { int sqlres = SQLSetStmtAttr(stm, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, SQL_IS_INTEGER); if (is_error(sqlres)) throw error_odbc(SQL_HANDLE_STMT, stm, "setting SQL_CURSOR_FORWARD_ONLY"); } void ODBCStatement::set_cursor_static() { int sqlres = SQLSetStmtAttr(stm, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_STATIC, SQL_IS_INTEGER); if (is_error(sqlres)) throw error_odbc(SQL_HANDLE_STMT, stm, "setting SQL_CURSOR_STATIC"); } void ODBCStatement::close_cursor() { int sqlres = SQLCloseCursor(stm); if (is_error(sqlres)) throw error_odbc(SQL_HANDLE_STMT, stm, "closing cursor"); #ifdef DEBUG_WARN_OPEN_TRANSACTIONS debug_reached_completion = true; #endif } void ODBCStatement::prepare(const char* query) { #ifdef DEBUG_WARN_OPEN_TRANSACTIONS if (!debug_reached_completion) { string msg = "Statement " + debug_query + " prepare was called before reaching completion"; fprintf(stderr, "-- %s\n", msg.c_str()); //throw error_consistency(msg); } #endif #ifdef DEBUG_WARN_OPEN_TRANSACTIONS debug_query = query; #endif // Casting out 'const' because ODBC API is not const-conscious if (is_error(SQLPrepare(stm, (unsigned char*)query, SQL_NTS))) error_odbc::throwf(SQL_HANDLE_STMT, stm, "compiling query \"%s\"", query); } void ODBCStatement::prepare(const char* query, int qlen) { #ifdef DEBUG_WARN_OPEN_TRANSACTIONS debug_query = string(query, qlen); #endif // Casting out 'const' because ODBC API is not const-conscious if (is_error(SQLPrepare(stm, (unsigned char*)query, qlen))) error_odbc::throwf(SQL_HANDLE_STMT, stm, "compiling query \"%.*s\"", qlen, query); } void ODBCStatement::prepare(const std::string& query) { prepare(query.data(), query.size()); } int ODBCStatement::execute() { #ifdef DEBUG_WARN_OPEN_TRANSACTIONS if (!debug_reached_completion) { string msg = "Statement " + debug_query + " restarted before reaching completion"; fprintf(stderr, "-- %s\n", msg.c_str()); //throw error_consistency(msg); } #endif int sqlres = SQLExecute(stm); if (is_error(sqlres)) throw error_odbc(SQL_HANDLE_STMT, stm, "executing precompiled query"); #ifdef DEBUG_WARN_OPEN_TRANSACTIONS debug_reached_completion = false; #endif return sqlres; } void ODBCStatement::close_cursor_if_needed() { /* // If the query raised an error that we are ignoring, closing the cursor // would raise invalid cursor state if (sqlres != SQL_ERROR) close_cursor(); #ifdef DEBUG_WARN_OPEN_TRANSACTIONS else if (sqlres == SQL_ERROR && error_is_ignored()) debug_reached_completion = true; #endif */ SQLCloseCursor(stm); #ifdef DEBUG_WARN_OPEN_TRANSACTIONS debug_reached_completion = true; #endif } void ODBCStatement::execute_ignoring_results() { execute_and_close(); } int ODBCStatement::execute_and_close() { int sqlres = SQLExecute(stm); if (is_error(sqlres)) throw error_odbc(SQL_HANDLE_STMT, stm, "executing precompiled query"); #ifdef DEBUG_WARN_OPEN_TRANSACTIONS debug_reached_completion = false; #endif close_cursor_if_needed(); return sqlres; } int ODBCStatement::exec_direct_and_close(const char* query, int qlen) { #ifdef DEBUG_WARN_OPEN_TRANSACTIONS debug_query = string(query, qlen); #endif // Casting out 'const' because ODBC API is not const-conscious int sqlres = SQLExecDirect(stm, (SQLCHAR*)query, qlen); if (is_error(sqlres)) error_odbc::throwf(SQL_HANDLE_STMT, stm, "executing query \"%.*s\"", qlen, query); #ifdef DEBUG_WARN_OPEN_TRANSACTIONS debug_reached_completion = false; #endif close_cursor_if_needed(); return sqlres; } int ODBCStatement::columns_count() { SQLSMALLINT res; int sqlres = SQLNumResultCols(stm, &res); if (is_error(sqlres)) throw error_odbc(SQL_HANDLE_STMT, stm, "querying number of columns in the result set"); return res; } Sequence::Sequence(ODBCConnection& conn, const char* name) : ODBCStatement(conn) { char qbuf[100]; int qlen; bind_out(1, out); if (conn.server_type == ServerType::ORACLE) qlen = snprintf(qbuf, 100, "SELECT %s.CurrVal FROM dual", name); else qlen = snprintf(qbuf, 100, "SELECT last_value FROM %s", name); prepare(qbuf, qlen); } Sequence::~Sequence() {} const int& Sequence::read() { if (is_error(SQLExecute(stm))) throw error_odbc(SQL_HANDLE_STMT, stm, "reading sequence value"); /* Get the result */ if (SQLFetch(stm) == SQL_NO_DATA) throw error_notfound("fetching results of sequence value reads"); if (is_error(SQLCloseCursor(stm))) throw error_odbc(SQL_HANDLE_STMT, stm, "closing sequence read cursor"); return out; } std::ostream& operator<<(std::ostream& o, const SQL_TIMESTAMP_STRUCT& t) { char buf[20]; snprintf(buf, 20, "%04d-%02d-%02d %02d:%02d:%02d.%d", t.year, t.month, t.day, t.hour, t.minute, t.second, t.fraction); o << buf; return o; } } // namespace db } // namespace dballe /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/db/odbc/station.h0000644000175000017500000001016412652630043014107 00000000000000/* * db/station - station table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_ODBC_STATION_H #define DBALLE_DB_ODBC_STATION_H #include #include #include #include namespace wreport { struct Var; } namespace dballe { namespace db { struct ODBCConnection; struct ODBCStatement; struct Sequence; namespace odbc { /** * Precompiled queries to manipulate the station table */ class ODBCStationBase : public sql::Station { protected: /** * DB connection. */ ODBCConnection& conn; /** Station ID sequence, when the DB requires it */ db::Sequence* seq_station; /** Precompiled select fixed station query */ ODBCStatement* sfstm; /** Precompiled select mobile station query */ ODBCStatement* smstm; /** Precompiled select data by station id query */ ODBCStatement* sstm; /** Precompiled insert query */ ODBCStatement* istm; /** Precompiled update query */ ODBCStatement* ustm; /** Precompiled delete query */ ODBCStatement* dstm; /** Station ID SQL parameter */ int id; /** Station latitude SQL parameter */ int lat; /** Station longitude SQL parameter */ int lon; /** Mobile station identifier SQL parameter */ char ident[64]; /** Mobile station identifier indicator */ SQLLEN ident_ind; /** * Set the mobile station identifier input value for this ::dba_db_station * * @param ident * Value to use for ident. NULL can be used to unset ident. */ void set_ident(const char* ident); /** * Get station information given a station ID * * @param id * ID of the station to query */ void get_data(int id); /** * Update the information about a station entry */ void update(); /** * Remove a station record */ void remove(); void impl_add_station_vars(const char* query, int id_station, Record& rec); public: ODBCStationBase(ODBCConnection& conn); ~ODBCStationBase(); ODBCStationBase(const ODBCStationBase&) = delete; ODBCStationBase(const ODBCStationBase&&) = delete; ODBCStationBase& operator=(const ODBCStationBase&) = delete; /** * Get the station ID given latitude, longitude and mobile identifier. * * It throws an exception if it does not exist. * * @return * Resulting ID of the station */ int get_id(int lat, int lon, const char* ident=NULL) override; /** * Get the station ID given latitude, longitude and mobile identifier. * * It creates the station record if it does not exist. * * @return * Resulting ID of the station */ int obtain_id(int lat, int lon, const char* ident=NULL, bool* inserted=NULL) override; void get_station_vars(int id_station, int id_report, std::function)> dest) override; void add_station_vars(int id_station, Record& rec) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; class ODBCStationV6 : public ODBCStationBase { public: ODBCStationV6(ODBCConnection& conn); void get_station_vars(int id_station, int id_report, std::function)> dest) override; void add_station_vars(int id_station, Record& rec) override; }; } } } #endif dballe-7.7/dballe/db/odbc/attrv6.h0000644000175000017500000000432612652630043013657 00000000000000/* * db/odbc/attrv6 - attribute table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_ODBC_ATTRV6_H #define DBALLE_DB_ODBC_ATTRV6_H #include #include namespace dballe { namespace db { namespace odbc { /** * Precompiled queries to manipulate the attr table */ class ODBCAttrV6 : public sql::AttrV6 { protected: /** DB connection. */ ODBCConnection& conn; /** Precompiled select statement */ ODBCStatement* sstm; /** id_data SQL parameter */ int id_data; /** attribute id SQL parameter */ wreport::Varcode type; /** attribute value SQL parameter */ char value[255]; /** attribute value indicator */ SQLLEN value_ind; public: ODBCAttrV6(ODBCConnection& conn); ~ODBCAttrV6(); void insert(Transaction& t, sql::bulk::InsertAttrsV6& vars, UpdateMode update_mode=UPDATE) override; /** * Load from the database all the attributes for var * * @param var * wreport::Var to which the resulting attributes will be added * @return * The error indicator for the function (See @ref error.h) */ void read(int id_data, std::function)> dest) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; private: // disallow copy ODBCAttrV6(const ODBCAttrV6&); ODBCAttrV6& operator=(const ODBCAttrV6&); }; } } } #endif dballe-7.7/dballe/db/odbc/datav6.h0000644000175000017500000000326412652630043013616 00000000000000/* * db/odbc/datav6 - data table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_ODBC_DATAV6_H #define DBALLE_DB_ODBC_DATAV6_H /** @file * @ingroup db * * Data table management used by the db module. */ #include #include namespace dballe { struct Record; namespace db { namespace odbc { struct DB; /** * Precompiled query to manipulate the data table */ class ODBCDataV6 : public sql::DataV6 { protected: /** DB connection. */ ODBCConnection& conn; public: ODBCDataV6(ODBCConnection& conn); ODBCDataV6(const ODBCDataV6&) = delete; ODBCDataV6(const ODBCDataV6&&) = delete; ODBCDataV6& operator=(const ODBCDataV6&) = delete; ~ODBCDataV6(); void insert(Transaction& t, sql::bulk::InsertV6& vars, UpdateMode update_mode=UPDATE) override; void remove(const v6::QueryBuilder& qb) override; void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/sqlite/0000755000175000017500000000000012653425050012726 500000000000000dballe-7.7/dballe/db/sqlite/internals-test.cc0000644000175000017500000001056312652630043016135 00000000000000#include "core/tests.h" #include "internals.h" using namespace std; using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; namespace { struct SQLiteFixture : Fixture { SQLiteConnection conn; SQLiteFixture() { conn.open_memory(); } void test_setup() { Fixture::test_setup(); conn.drop_table_if_exists("dballe_test"); conn.exec("CREATE TABLE dballe_test (val INTEGER NOT NULL)"); } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("query_int", [](Fixture& f) { // Test querying int values f.conn.exec("INSERT INTO dballe_test VALUES (1)"); f.conn.exec("INSERT INTO dballe_test VALUES (2)"); auto s = f.conn.sqlitestatement("SELECT val FROM dballe_test"); int val = 0; unsigned count = 0; s->execute([&]() { val += s->column_int(0); ++count; }); wassert(actual(count) == 2); wassert(actual(val) == 3); }); add_method("query_int_null", [](Fixture& f) { // Test querying int values, with potential NULLs f.conn.exec("CREATE TABLE dballe_testnull (val INTEGER)"); f.conn.exec("INSERT INTO dballe_testnull VALUES (NULL)"); f.conn.exec("INSERT INTO dballe_testnull VALUES (42)"); auto s = f.conn.sqlitestatement("SELECT val FROM dballe_testnull"); int val = 0; unsigned count = 0; unsigned countnulls = 0; s->execute([&]() { if (s->column_isnull(0)) ++countnulls; else val += s->column_int(0); ++count; }); wassert(actual(val) == 42); wassert(actual(count) == 2); wassert(actual(countnulls) == 1); }); add_method("query_unsigned", [](Fixture& f) { // Test querying unsigned values f.conn.exec("INSERT INTO dballe_test VALUES (0xFFFFFFFE)"); auto s = f.conn.sqlitestatement("SELECT val FROM dballe_test"); unsigned val = 0; unsigned count = 0; s->execute([&]() { val += s->column_int64(0); ++count; }); wassert(actual(count) == 1); wassert(actual(val) == 0xFFFFFFFE); }); add_method("query_unsigned_short", [](Fixture& f) { // Test querying unsigned short values char buf[200]; snprintf(buf, 200, "INSERT INTO dballe_test VALUES (%d)", (int)WR_VAR(3, 1, 12)); f.conn.exec(buf); auto s = f.conn.sqlitestatement("SELECT val FROM dballe_test"); Varcode val = 0; unsigned count = 0; s->execute([&]() { val = (Varcode)s->column_int(0); ++count; }); wassert(actual(count) == 1); wassert(actual(val) == WR_VAR(3, 1, 12)); }); add_method("query_has_tables", [](Fixture& f) { // Test has_tables wassert(actual(f.conn.has_table("this_should_not_exist")).isfalse()); wassert(actual(f.conn.has_table("dballe_test")).istrue()); }); add_method("query_settings", [](Fixture& f) { // Test settings f.conn.drop_table_if_exists("dballe_settings"); wassert(actual(f.conn.has_table("dballe_settings")).isfalse()); wassert(actual(f.conn.get_setting("test_key")) == ""); f.conn.set_setting("test_key", "42"); wassert(actual(f.conn.has_table("dballe_settings")).istrue()); wassert(actual(f.conn.get_setting("test_key")) == "42"); }); add_method("auto_increment", [](Fixture& f) { // Test auto_increment f.conn.exec("CREATE TABLE dballe_testai (id INTEGER PRIMARY KEY, val INTEGER)"); f.conn.exec("INSERT INTO dballe_testai (val) VALUES (42)"); wassert(actual(f.conn.get_last_insert_id()) == 1); f.conn.exec("INSERT INTO dballe_testai (val) VALUES (43)"); wassert(actual(f.conn.get_last_insert_id()) == 2); }); } }; Tests tests("db_internals_sqlite"); } dballe-7.7/dballe/db/sqlite/repinfo.cc0000644000175000017500000001162212652630043014620 00000000000000/* * db/sqlite/repinfo - repinfo table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "repinfo.h" #include "dballe/db/db.h" #include "dballe/db/sqlite/internals.h" using namespace wreport; using namespace std; namespace dballe { namespace db { namespace sqlite { SQLiteRepinfoBase::SQLiteRepinfoBase(SQLiteConnection& conn) : Repinfo(conn), conn(conn) { read_cache(); } SQLiteRepinfoBase::~SQLiteRepinfoBase() { } void SQLiteRepinfoBase::read_cache() { cache.clear(); memo_idx.clear(); auto stm = conn.sqlitestatement("SELECT id, memo, description, prio, descriptor, tablea FROM repinfo ORDER BY id"); stm->execute([&]() { string memo = stm->column_string(1); string desc = stm->column_string(2); string descriptor = stm->column_string(4); cache_append( stm->column_int(0), memo.c_str(), desc.c_str(), stm->column_int(3), descriptor.c_str(), stm->column_int(5) ); }); // Rebuild the memo index as well rebuild_memo_idx(); } void SQLiteRepinfoBase::insert_auto_entry(const char* memo) { auto stm = conn.sqlitestatement("SELECT MAX(id) FROM repinfo"); unsigned id; stm->execute_one([&]() { id = stm->column_int(0); }); stm = conn.sqlitestatement("SELECT MAX(prio) FROM repinfo"); unsigned prio; stm->execute_one([&]() { prio = stm->column_int(0); }); ++id; ++prio; stm = conn.sqlitestatement(R"( INSERT INTO repinfo (id, memo, description, prio, descriptor, tablea) VALUES (?, ?, ?, ?, '-', 255) )"); stm->bind(id, memo, memo, prio); stm->execute(); } int SQLiteRepinfoBase::id_use_count(unsigned id, const char* name) { unsigned count = 0; auto stm = conn.sqlitestatement("SELECT COUNT(1) FROM context WHERE id_report=?"); stm->bind(id); stm->execute_one([&]() { count = stm->column_int(0); }); return count; } void SQLiteRepinfoBase::delete_entry(unsigned id) { auto stm = conn.sqlitestatement("DELETE FROM repinfo WHERE id=?"); stm->bind(id); stm->execute(); } void SQLiteRepinfoBase::update_entry(const sql::repinfo::Cache& entry) { auto stm = conn.sqlitestatement(R"( UPDATE repinfo set memo=?, description=?, prio=?, descriptor=?, tablea=? WHERE id=? )"); stm->bind( entry.new_memo, entry.new_desc, entry.new_prio, entry.new_descriptor.c_str(), entry.new_tablea, entry.id); stm->execute(); } void SQLiteRepinfoBase::insert_entry(const sql::repinfo::Cache& entry) { auto stm = conn.sqlitestatement(R"( INSERT INTO repinfo (id, memo, description, prio, descriptor, tablea) VALUES (?, ?, ?, ?, ?, ?) )"); stm->bind( entry.id, entry.new_memo, entry.new_desc, entry.new_prio, entry.new_descriptor, entry.new_tablea); stm->execute(); } void SQLiteRepinfoBase::dump(FILE* out) { fprintf(out, "dump of table repinfo:\n"); fprintf(out, " id memo description prio desc tablea\n"); int count = 0; auto stm = conn.sqlitestatement("SELECT id, memo, description, prio, descriptor, tablea FROM repinfo ORDER BY id"); stm->execute([&]() { string memo = stm->column_string(1); string desc = stm->column_string(2); string descriptor = stm->column_string(4); fprintf(out, " %4d %s %s %d %s %d\n", stm->column_int(0), memo.c_str(), desc.c_str(), stm->column_int(3), descriptor.c_str(), stm->column_int(5)); ++count; }); fprintf(out, "%d element%s in table repinfo\n", count, count != 1 ? "s" : ""); } SQLiteRepinfoV6::SQLiteRepinfoV6(SQLiteConnection& conn) : SQLiteRepinfoBase(conn) {} int SQLiteRepinfoV6::id_use_count(unsigned id, const char* name) { unsigned count = 0; auto stm = conn.sqlitestatement("SELECT COUNT(1) FROM data WHERE id_report=?"); stm->bind(id); stm->execute_one([&]() { count = stm->column_int(0); }); return count; } } } } dballe-7.7/dballe/db/sqlite/levtr.h0000644000175000017500000000453312652630043014157 00000000000000/* * db/v6/lev_tr - lev_tr table management * * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQLITE_LEVTRV6_H #define DBALLE_DB_SQLITE_LEVTRV6_H #include #include #include #include #include namespace dballe { struct Record; struct Msg; namespace msg { struct Context; } namespace db { struct Connection; struct Statement; namespace sqlite { struct DB; /** * Precompiled queries to manipulate the lev_tr table */ struct SQLiteLevTrV6 : public sql::LevTr { protected: /** * DB connection. */ SQLiteConnection& conn; /** Precompiled select statement */ SQLiteStatement* sstm = nullptr; /** Precompiled select data statement */ SQLiteStatement* sdstm = nullptr; /** Precompiled insert statement */ SQLiteStatement* istm = nullptr; /** Precompiled delete statement */ SQLiteStatement* dstm = nullptr; DBRow working_row; public: SQLiteLevTrV6(SQLiteConnection& conn); SQLiteLevTrV6(const LevTr&) = delete; SQLiteLevTrV6(const LevTr&&) = delete; SQLiteLevTrV6& operator=(const SQLiteLevTrV6&) = delete; ~SQLiteLevTrV6(); /** * Return the ID for the given Level and Trange, adding it to the database * if it does not already exist */ int obtain_id(const Level& lev, const Trange& tr) override; const DBRow* read(int id) override; void read_all(std::function dest) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/sqlite/driver.cc0000644000175000017500000001616512652630043014460 00000000000000/* * db/sqlite/driver - Backend SQLite driver * * Copyright (C) 2014--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "driver.h" #include "repinfo.h" #include "station.h" #include "levtr.h" #include "datav6.h" #include "attrv6.h" #include "dballe/db/v6/qbuilder.h" #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace sqlite { Driver::Driver(SQLiteConnection& conn) : conn(conn) { } Driver::~Driver() { } std::unique_ptr Driver::create_repinfov6() { return unique_ptr(new SQLiteRepinfoV6(conn)); } std::unique_ptr Driver::create_stationv6() { return unique_ptr(new SQLiteStationV6(conn)); } std::unique_ptr Driver::create_levtrv6() { return unique_ptr(new SQLiteLevTrV6(conn)); } std::unique_ptr Driver::create_datav6() { return unique_ptr(new SQLiteDataV6(conn)); } std::unique_ptr Driver::create_attrv6() { return unique_ptr(new SQLiteAttrV6(conn)); } void Driver::run_built_query_v6( const v6::QueryBuilder& qb, std::function dest) { auto stm = conn.sqlitestatement(qb.sql_query); if (qb.bind_in_ident) stm->bind_val(1, qb.bind_in_ident); sql::SQLRecordV6 rec; stm->execute([&]() { int output_seq = 0; if (qb.select_station) { rec.out_ana_id = stm->column_int(output_seq++); rec.out_lat = stm->column_int(output_seq++); rec.out_lon = stm->column_int(output_seq++); if (stm->column_isnull(output_seq)) { rec.out_ident_size = -1; rec.out_ident[0] = 0; } else { const char* ident = stm->column_string(output_seq); rec.out_ident_size = min(strlen(ident), (string::size_type)63); memcpy(rec.out_ident, ident, rec.out_ident_size); rec.out_ident[rec.out_ident_size] = 0; } ++output_seq; } if (qb.select_varinfo) { rec.out_rep_cod = stm->column_int(output_seq++); rec.out_id_ltr = stm->column_int(output_seq++); rec.out_varcode = stm->column_int(output_seq++); } if (qb.select_data_id) rec.out_id_data = stm->column_int(output_seq++); if (qb.select_data) { rec.out_datetime = stm->column_datetime(output_seq++); const char* value = stm->column_string(output_seq++); unsigned val_size = min(strlen(value), (string::size_type)255); memcpy(rec.out_value, value, val_size); rec.out_value[val_size] = 0; } if (qb.select_summary_details) { rec.out_id_data = stm->column_int(output_seq++); rec.out_datetime = stm->column_datetime(output_seq++); rec.out_datetimemax = stm->column_datetime(output_seq++); } dest(rec); }); } void Driver::create_tables_v6() { conn.exec(R"( CREATE TABLE station ( id INTEGER PRIMARY KEY, lat INTEGER NOT NULL, lon INTEGER NOT NULL, ident CHAR(64), UNIQUE (lat, lon, ident) ); CREATE INDEX pa_lon ON station(lon); )"); conn.exec(R"( CREATE TABLE repinfo ( id INTEGER PRIMARY KEY, memo VARCHAR(30) NOT NULL, description VARCHAR(255) NOT NULL, prio INTEGER NOT NULL, descriptor CHAR(6) NOT NULL, tablea INTEGER NOT NULL, UNIQUE (prio), UNIQUE (memo) ); )"); conn.exec(R"( CREATE TABLE lev_tr ( id INTEGER PRIMARY KEY, ltype1 INTEGER NOT NULL, l1 INTEGER NOT NULL, ltype2 INTEGER NOT NULL, l2 INTEGER NOT NULL, ptype INTEGER NOT NULL, p1 INTEGER NOT NULL, p2 INTEGER NOT NULL, UNIQUE (ltype1, l1, ltype2, l2, ptype, p1, p2) ); )"); conn.exec(R"( CREATE TABLE data ( id INTEGER PRIMARY KEY, id_station INTEGER NOT NULL REFERENCES station (id) ON DELETE CASCADE, id_report INTEGER NOT NULL REFERENCES repinfo (id) ON DELETE CASCADE, id_lev_tr INTEGER NOT NULL, datetime TEXT NOT NULL, id_var INTEGER NOT NULL, value VARCHAR(255) NOT NULL, UNIQUE (id_station, datetime, id_lev_tr, id_report, id_var) ); CREATE INDEX data_report ON data(id_report); CREATE INDEX data_lt ON data(id_lev_tr); )"); conn.exec(R"( CREATE TABLE attr ( id_data INTEGER NOT NULL REFERENCES data (id) ON DELETE CASCADE, type INTEGER NOT NULL, value VARCHAR(255) NOT NULL, UNIQUE (id_data, type) ); )"); conn.set_setting("version", "V6"); } void Driver::delete_tables_v6() { conn.drop_table_if_exists("attr"); conn.drop_table_if_exists("data"); conn.drop_table_if_exists("lev_tr"); conn.drop_table_if_exists("repinfo"); conn.drop_table_if_exists("station"); conn.drop_settings(); } void Driver::vacuum_v6() { conn.exec(R"( DELETE FROM lev_tr WHERE id IN ( SELECT ltr.id FROM lev_tr ltr LEFT JOIN data d ON d.id_lev_tr = ltr.id WHERE d.id_lev_tr is NULL) )"); conn.exec(R"( DELETE FROM station WHERE id IN ( SELECT p.id FROM station p LEFT JOIN data d ON d.id_station = p.id WHERE d.id is NULL) )"); } void Driver::exec_no_data(const std::string& query) { conn.exec(query); } void Driver::explain(const std::string& query) { string explain_query = "EXPLAIN QUERY PLAN "; explain_query += query; fprintf(stderr, "%s\n", explain_query.c_str()); auto stm = conn.sqlitestatement(explain_query); fprintf(stderr, "sid\torder\tfrom\tdetail\n"); stm->execute([&]() { int selectid = stm->column_int(0); int order = stm->column_int(1); int from = stm->column_int(2); const char* detail = stm->column_string(3); fprintf(stderr, "%d\t%d\t%d\t%s\n", selectid, order, from, detail); }); } } } } dballe-7.7/dballe/db/sqlite/repinfo.h0000644000175000017500000000427712652630043014472 00000000000000/* * db/sqlite/repinfo - repinfo table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQLITE_REPINFO_H #define DBALLE_DB_SQLITE_REPINFO_H #include #include #include #include namespace dballe { struct Record; namespace db { struct SQLiteConnection; namespace sqlite { /** * Fast cached access to the repinfo table */ struct SQLiteRepinfoBase : public sql::Repinfo { /** * DB connection. The pointer is assumed always valid during the * lifetime of the object */ SQLiteConnection& conn; SQLiteRepinfoBase(SQLiteConnection& conn); SQLiteRepinfoBase(const SQLiteRepinfoBase&) = delete; SQLiteRepinfoBase(const SQLiteRepinfoBase&&) = delete; virtual ~SQLiteRepinfoBase(); SQLiteRepinfoBase& operator=(const SQLiteRepinfoBase&) = delete; void dump(FILE* out) override; protected: /// Return how many time this ID is used in the database int id_use_count(unsigned id, const char* name) override; void delete_entry(unsigned id) override; void update_entry(const sql::repinfo::Cache& entry) override; void insert_entry(const sql::repinfo::Cache& entry) override; void read_cache() override; void insert_auto_entry(const char* memo) override; }; struct SQLiteRepinfoV6 : public SQLiteRepinfoBase { SQLiteRepinfoV6(SQLiteConnection& conn); protected: int id_use_count(unsigned id, const char* name) override; }; } } } #endif dballe-7.7/dballe/db/sqlite/levtr.cc0000644000175000017500000000770712652630043014323 00000000000000#include "levtr.h" #include "dballe/core/defs.h" #include "dballe/msg/msg.h" #include #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace sqlite { namespace { Level to_level(SQLiteStatement& stm, int first_id=0) { return Level( stm.column_int(first_id), stm.column_int(first_id + 1), stm.column_int(first_id + 2), stm.column_int(first_id + 3)); } Trange to_trange(SQLiteStatement& stm, int first_id=0) { return Trange( stm.column_int(first_id), stm.column_int(first_id + 1), stm.column_int(first_id + 2)); } } SQLiteLevTrV6::SQLiteLevTrV6(SQLiteConnection& conn) : conn(conn) { const char* select_query = "SELECT id FROM lev_tr WHERE" " ltype1=? AND l1=? AND ltype2=? AND l2=?" " AND ptype=? AND p1=? AND p2=?"; const char* select_data_query = "SELECT ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr WHERE id=?"; const char* insert_query = "INSERT INTO lev_tr (ltype1, l1, ltype2, l2, ptype, p1, p2) VALUES (?, ?, ?, ?, ?, ?, ?)"; // Create the statement for select fixed sstm = conn.sqlitestatement(select_query).release(); // Create the statement for select data sdstm = conn.sqlitestatement(select_data_query).release(); // Create the statement for insert istm = conn.sqlitestatement(insert_query).release(); } SQLiteLevTrV6::~SQLiteLevTrV6() { delete sstm; delete sdstm; delete istm; } int SQLiteLevTrV6::obtain_id(const Level& lev, const Trange& tr) { sstm->bind(lev.ltype1, lev.l1, lev.ltype2, lev.l2, tr.pind, tr.p1, tr.p2); int id = -1; sstm->execute_one([&]() { id = sstm->column_int(0); }); // If there is an existing record, use its ID and don't do an INSERT if (id != -1) return id; istm->bind(lev.ltype1, lev.l1, lev.ltype2, lev.l2, tr.pind, tr.p1, tr.p2); istm->execute(); return conn.get_last_insert_id(); } const sql::LevTr::DBRow* SQLiteLevTrV6::read(int id) { sdstm->bind(id); bool found = false; sdstm->execute([&]() { working_row.id = id; working_row.ltype1 = sdstm->column_int(0); working_row.l1 = sdstm->column_int(1); working_row.ltype2 = sdstm->column_int(2); working_row.l2 = sdstm->column_int(3); working_row.pind = sdstm->column_int(4); working_row.p1 = sdstm->column_int(5); working_row.p2 = sdstm->column_int(6); found = true; }); if (!found) return nullptr; return &working_row; } void SQLiteLevTrV6::read_all(std::function dest) { auto stm = conn.sqlitestatement("SELECT id, ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr"); stm->execute([&]() { working_row.id = stm->column_int(0); working_row.ltype1 = stm->column_int(1); working_row.l1 = stm->column_int(2); working_row.ltype2 = stm->column_int(3); working_row.l2 = stm->column_int(4); working_row.pind = stm->column_int(5); working_row.p1 = stm->column_int(6); working_row.p2 = stm->column_int(7); dest(working_row); }); } void SQLiteLevTrV6::dump(FILE* out) { int count = 0; fprintf(out, "dump of table lev_tr:\n"); fprintf(out, " id lev tr\n"); auto stm = conn.sqlitestatement("SELECT id, ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr ORDER BY ID"); stm->execute([&]() { fprintf(out, " %4d ", stm->column_int(0)); { stringstream str; str << to_level(*stm, 1); fprintf(out, "%-20s ", str.str().c_str()); } { stringstream str; str << to_trange(*stm, 5); fprintf(out, "%-10s\n", str.str().c_str()); } ++count; }); fprintf(out, "%d element%s in table lev_tr\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/sqlite/internals.h0000644000175000017500000001710412652630043015020 00000000000000/* * db/sqlite/internals - Implementation infrastructure for the SQLite DB connection * * Copyright (C) 2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQLITE_INTERNALS_H #define DBALLE_DB_SQLITE_INTERNALS_H #include #include #include namespace dballe { namespace db { struct SQLiteStatement; /** * Report an SQLite error */ struct error_sqlite : public db::error { std::string msg; /** * Copy informations from the ODBC diagnostic record to the dba error * report */ error_sqlite(sqlite3* db, const std::string& msg); error_sqlite(const std::string& dbmsg, const std::string& msg); ~error_sqlite() throw () {} wreport::ErrorCode code() const throw () { return wreport::WR_ERR_ODBC; } virtual const char* what() const throw () { return msg.c_str(); } static void throwf(sqlite3* db, const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3); }; /// Database connection class SQLiteConnection : public Connection { protected: /// Database connection sqlite3* db = nullptr; protected: void init_after_connect(); public: SQLiteConnection(); SQLiteConnection(const SQLiteConnection&) = delete; SQLiteConnection(const SQLiteConnection&&) = delete; ~SQLiteConnection(); SQLiteConnection& operator=(const SQLiteConnection&) = delete; operator sqlite3*() { return db; } void open_file(const std::string& pathname, int flags=SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); void open_memory(int flags=SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); void open_private_file(int flags=SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); std::unique_ptr transaction() override; std::unique_ptr sqlitestatement(const std::string& query); /// Check if the database contains a table bool has_table(const std::string& name) override; /** * Get a value from the settings table. * * Returns the empty string if the table does not exist. */ std::string get_setting(const std::string& key) override; /** * Set a value in the settings table. * * The table is created if it does not exist. */ void set_setting(const std::string& key, const std::string& value) override; /// Drop the settings table void drop_settings() override; /** * Delete a table in the database if it exists, otherwise do nothing. */ void drop_table_if_exists(const char* name); /** * Return LAST_INSERT_ID or LAST_INSER_ROWID or whatever is appropriate for * the current database, if supported. * * If not supported, an exception is thrown. */ int get_last_insert_id(); /// Count the number of rows modified by the last query that was run int changes(); /// Wrap sqlite3_exec, without a callback void exec(const std::string& query); void exec_nothrow(const std::string& query) noexcept; }; /// SQLite statement struct SQLiteStatement { SQLiteConnection& conn; sqlite3_stmt *stm = nullptr; SQLiteStatement(SQLiteConnection& conn, const std::string& query); SQLiteStatement(const SQLiteStatement&) = delete; SQLiteStatement(const SQLiteStatement&&) = delete; ~SQLiteStatement(); SQLiteStatement& operator=(const SQLiteStatement&) = delete; /** * Bind all the arguments in a single invocation. * * Note that the parameter positions are used as bind column numbers, so * calling this function twice will re-bind columns instead of adding new * ones. */ template void bind(const Args& ...args) { bindn(args...); } void bind_null_val(int idx); void bind_val(int idx, int val); void bind_val(int idx, unsigned val); void bind_val(int idx, unsigned short val); void bind_val(int idx, const Datetime& val); void bind_val(int idx, const char* val); // Warning: SQLITE_STATIC is used void bind_val(int idx, const std::string& val); // Warning: SQLITE_STATIC is used /// Run the query, ignoring all results void execute(); /** * Run the query, calling on_row for every row in the result. * * At the end of the function, the statement is reset, even in case an * exception is thrown. */ void execute(std::function on_row); /** * Run the query, raising an error if there is more than one row in the * result */ void execute_one(std::function on_row); /// Read the int value of a column in the result set (0-based) int column_int(int col) { return sqlite3_column_int(stm, col); } /// Read the int value of a column in the result set (0-based) sqlite3_int64 column_int64(int col) { return sqlite3_column_int64(stm, col); } /// Read the double value of a column in the result set (0-based) double column_double(int col) { return sqlite3_column_double(stm, col); } /// Read the string value of a column in the result set (0-based) const char* column_string(int col) { return (const char*)sqlite3_column_text(stm, col); } /// Read the string value of a column and parse it as a Datetime Datetime column_datetime(int col); /// Check if a column has a NULL value (0-based) bool column_isnull(int col) { return sqlite3_column_type(stm, col) == SQLITE_NULL; } void wrap_sqlite3_reset(); void wrap_sqlite3_reset_nothrow() noexcept; /** * Get the current error message, reset the statement and throw * error_sqlite */ [[noreturn]] void reset_and_throw(const std::string& errmsg); operator sqlite3_stmt*() { return stm; } #if 0 /// @return SQLExecute's result int execute(); /// @return SQLExecute's result int exec_direct(const char* query); /// @return SQLExecute's result int exec_direct(const char* query, int qlen); /// @return SQLExecute's result int execute_and_close(); /// @return SQLExecute's result int exec_direct_and_close(const char* query); /// @return SQLExecute's result int exec_direct_and_close(const char* query, int qlen); /** * @return the number of columns in the result set (or 0 if the statement * did not return columns) */ int columns_count(); bool fetch(); bool fetch_expecting_one(); void close_cursor(); void close_cursor_if_needed(); /// Row count for select operations size_t select_rowcount(); /// Row count for insert, delete and other non-select operations size_t rowcount(); #endif private: // Implementation of variadic bind: terminating condition template void bindn() {} // Implementation of variadic bind: recursive iteration over the parameter pack template void bindn(const T& first, const Args& ...args) { bind_val(total - sizeof...(args), first); bindn(args...); } }; } } #endif dballe-7.7/dballe/db/sqlite/driver.h0000644000175000017500000000341412652630043014313 00000000000000/* * db/sqlite/driver - Backend SQLite driver * * Copyright (C) 2014--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQLITE_DRIVER_H #define DBALLE_DB_SQLITE_DRIVER_H #include namespace dballe { namespace db { struct SQLiteConnection; namespace sqlite { struct Driver : public sql::Driver { SQLiteConnection& conn; Driver(SQLiteConnection& conn); virtual ~Driver(); std::unique_ptr create_repinfov6() override; std::unique_ptr create_stationv6() override; std::unique_ptr create_levtrv6() override; std::unique_ptr create_datav6() override; std::unique_ptr create_attrv6() override; void run_built_query_v6(const v6::QueryBuilder& qb, std::function dest) override; void create_tables_v6() override; void delete_tables_v6() override; void vacuum_v6() override; void exec_no_data(const std::string& query) override; void explain(const std::string& query) override; }; } } } #endif dballe-7.7/dballe/db/sqlite/station.cc0000644000175000017500000001270012652630043014635 00000000000000#include "station.h" #include "dballe/db/sqlite/internals.h" #include "dballe/record.h" #include "dballe/core/var.h" #include using namespace wreport; using namespace dballe::db; using namespace std; namespace dballe { namespace db { namespace sqlite { SQLiteStationBase::SQLiteStationBase(SQLiteConnection& conn) : conn(conn) { const char* select_fixed_query = "SELECT id FROM station WHERE lat=? AND lon=? AND ident IS NULL"; const char* select_mobile_query = "SELECT id FROM station WHERE lat=? AND lon=? AND ident=?"; const char* insert_query = "INSERT INTO station (lat, lon, ident)" " VALUES (?, ?, ?);"; // Create the statement for select fixed sfstm = conn.sqlitestatement(select_fixed_query).release(); // Create the statement for select mobile smstm = conn.sqlitestatement(select_mobile_query).release(); // Create the statement for insert istm = conn.sqlitestatement(insert_query).release(); } SQLiteStationBase::~SQLiteStationBase() { delete sfstm; delete smstm; delete istm; } bool SQLiteStationBase::maybe_get_id(int lat, int lon, const char* ident, int* id) { SQLiteStatement* s; if (ident) { smstm->bind_val(1, lat); smstm->bind_val(2, lon); smstm->bind_val(3, ident); s = smstm; } else { sfstm->bind_val(1, lat); sfstm->bind_val(2, lon); s = sfstm; } bool found = false; s->execute([&]() { found = true; *id = s->column_int(0); }); return found; } int SQLiteStationBase::get_id(int lat, int lon, const char* ident) { int id; if (maybe_get_id(lat, lon, ident, &id)) return id; throw error_notfound("station not found in the database"); } int SQLiteStationBase::obtain_id(int lat, int lon, const char* ident, bool* inserted) { int id; if (maybe_get_id(lat, lon, ident, &id)) { if (inserted) *inserted = false; return id; } // If no station was found, insert a new one istm->bind_val(1, lat); istm->bind_val(2, lon); if (ident) istm->bind_val(3, ident); else istm->bind_null_val(3); istm->execute(); if (inserted) *inserted = true; return conn.get_last_insert_id(); } void SQLiteStationBase::read_station_vars(SQLiteStatement& stm, std::function)> dest) { // Retrieve results Varcode last_varcode = 0; unique_ptr var; stm.execute([&]() { Varcode code = stm.column_int(0); TRACE("fill_ana_layer Got B%02ld%03ld %s\n", WR_VAR_X(code), WR_VAR_Y(code), out_value); // First process the variable, possibly inserting the old one in the message if (last_varcode != code) { TRACE("fill_ana_layer new var\n"); if (var.get()) { TRACE("fill_ana_layer inserting old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } var = newvar(code, stm.column_string(1)); last_varcode = code; } if (!stm.column_isnull(2)) { TRACE("fill_ana_layer new attribute\n"); var->seta(newvar(stm.column_int(2), stm.column_string(3))); } }); if (var.get()) { TRACE("fill_ana_layer inserting leftover old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } } void SQLiteStationBase::get_station_vars(int id_station, int id_report, std::function)> dest) { // Perform the query static const char query[] = R"( SELECT d.id_var, d.value, a.type, a.value FROM data d LEFT JOIN attr a ON a.id_data = d.id WHERE d.id_station=? AND d.id_report=? AND d.id_lev_tr = -1 ORDER BY d.id_var, a.type )"; auto stm = conn.sqlitestatement(query); stm->bind(id_station, id_report); TRACE("fill_ana_layer Performing query: %s with idst %d idrep %d\n", query, id_station, id_report); read_station_vars(*stm, dest); } void SQLiteStationBase::dump(FILE* out) { int count = 0; fprintf(out, "dump of table station:\n"); auto stm = conn.sqlitestatement("SELECT id, lat, lon, ident FROM station"); stm->execute([&]() { fprintf(out, " %d, %.5f, %.5f", stm->column_int(0), stm->column_int(1) / 100000.0, stm->column_int(2) / 100000.0); if (stm->column_isnull(3)) putc('\n', out); else fprintf(out, ", %s\n", stm->column_string(3)); ++count; }); fprintf(out, "%d element%s in table station\n", count, count != 1 ? "s" : ""); } void SQLiteStationBase::add_station_vars(int id_station, Record& rec) { const char* query = R"( SELECT d.id_var, d.value FROM data d, repinfo ri WHERE d.id_lev_tr = -1 AND ri.id = d.id_report AND d.id_station = ? AND ri.prio=( SELECT MAX(sri.prio) FROM repinfo sri JOIN data sd ON sri.id=sd.id_report WHERE sd.id_station=d.id_station AND sd.id_lev_tr = -1 AND sd.id_var=d.id_var) )"; auto stm = conn.sqlitestatement(query); stm->bind(id_station); stm->execute([&]() { rec.set(newvar((wreport::Varcode)stm->column_int(0), stm->column_string(1))); }); } SQLiteStationV6::SQLiteStationV6(SQLiteConnection& conn) : SQLiteStationBase(conn) {} } } } dballe-7.7/dballe/db/sqlite/datav6.cc0000644000175000017500000001115012652630043014337 00000000000000#include "datav6.h" #include "dballe/db/sql.h" #include "dballe/db/querybuf.h" #include "dballe/db/v6/qbuilder.h" #include "dballe/record.h" #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace sqlite { SQLiteDataV6::SQLiteDataV6(SQLiteConnection& conn) : conn(conn) { // Create the statement for select id sstm = conn.sqlitestatement(R"( SELECT id, id_lev_tr, id_var, value FROM data WHERE id_station=? AND id_report=? AND datetime=? ORDER BY id_lev_tr, id_var )").release(); } SQLiteDataV6::~SQLiteDataV6() { if (sstm) delete sstm; } void SQLiteDataV6::insert(Transaction& t, sql::bulk::InsertV6& vars, UpdateMode update_mode) { // Get the current status of variables for this context sstm->bind_val(1, vars.id_station); sstm->bind_val(2, vars.id_report); sstm->bind_val(3, vars.datetime); // Scan the result in parallel with the variable list, annotating changed // items with their data ID sql::bulk::AnnotateVarsV6 todo(vars); sstm->execute([&]() { todo.annotate( sstm->column_int(0), sstm->column_int(1), sstm->column_int(2), sstm->column_string(3)); }); todo.annotate_end(); // We now have a todo-list switch (update_mode) { case UPDATE: if (todo.do_update) { auto update_stm = conn.sqlitestatement("UPDATE data SET value=? WHERE id=?"); for (auto& v: vars) { if (!v.needs_update()) continue; // Warning: we do not know if v.var is a string, so the result of // enqc is only valid until another enqc is called update_stm->bind(v.var->enqc(), v.id_data); update_stm->execute(); v.set_updated(); } } break; case IGNORE: break; case ERROR: if (todo.do_update) throw error_consistency("refusing to overwrite existing data"); } if (todo.do_insert) { Querybuf dq(512); dq.appendf(R"( INSERT INTO data (id_station, id_report, id_lev_tr, datetime, id_var, value) VALUES (%d, %d, ?, '%04d-%02d-%02d %02d:%02d:%02d', ?, ?) )", vars.id_station, vars.id_report, vars.datetime.year, vars.datetime.month, vars.datetime.day, vars.datetime.hour, vars.datetime.minute, vars.datetime.second); auto insert = conn.sqlitestatement(dq); for (auto& v: vars) { if (!v.needs_insert()) continue; // Warning: we do not know if v.var is a string, so the result of // enqc is only valid until another enqc is called insert->bind(v.id_levtr, v.var->code(), v.var->enqc()); insert->execute(); v.id_data = conn.get_last_insert_id(); v.set_inserted(); } } } void SQLiteDataV6::remove(const v6::QueryBuilder& qb) { auto stmd = conn.sqlitestatement("DELETE FROM data WHERE id=?"); auto stm = conn.sqlitestatement(qb.sql_query); if (qb.bind_in_ident) stm->bind_val(1, qb.bind_in_ident); // Iterate all the data_id results, deleting the related data and attributes stm->execute([&]() { // Compile the DELETE query for the data stmd->bind_val(1, stm->column_int(0)); stmd->execute(); }); } void SQLiteDataV6::dump(FILE* out) { int count = 0; fprintf(out, "dump of table data:\n"); fprintf(out, " id st rep ltr datetime var\n"); auto stm = conn.sqlitestatement("SELECT id, id_station, id_report, id_lev_tr, datetime, id_var, value FROM data"); stm->execute([&]() { int id_lev_tr = stm->column_int(3); const char* datetime = stm->column_string(4); Varcode code = stm->column_int(5); char ltr[20]; if (id_lev_tr == -1) strcpy(ltr, "----"); else snprintf(ltr, 20, "%04d", id_lev_tr); fprintf(out, " %4d %4d %3d %s %s %01d%02d%03d", stm->column_int(0), stm->column_int(1), stm->column_int(2), ltr, datetime, WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code)); if (stm->column_isnull(6)) fprintf(out, "\n"); else fprintf(out, " %s\n", stm->column_string(6)); ++count; }); fprintf(out, "%d element%s in table data\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/sqlite/attrv6.cc0000644000175000017500000001112412652630043014401 00000000000000/* * db/sqlite/attrv6 - attribute table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "attrv6.h" #include "dballe/db/sql/internals.h" #include "dballe/db/querybuf.h" #include "dballe/var.h" using namespace std; using namespace wreport; namespace dballe { namespace db { namespace sqlite { SQLiteAttrV6::SQLiteAttrV6(SQLiteConnection& conn) : conn(conn) { // Precompile the statement for select sstm = conn.sqlitestatement("SELECT type, value FROM attr WHERE id_data=?").release(); } SQLiteAttrV6::~SQLiteAttrV6() { delete sstm; delete istm; delete ustm; } void SQLiteAttrV6::read(int id_data, function)> dest) { sstm->bind_val(1, id_data); sstm->execute([&]() { if (sstm->column_isnull(1)) dest(newvar(sstm->column_int(0))); else dest(newvar(sstm->column_int(0), sstm->column_string(1))); }); } void SQLiteAttrV6::insert(Transaction& t, sql::bulk::InsertAttrsV6& attrs, UpdateMode update_mode) { Querybuf select_query; select_query.append("SELECT id_data, type, value FROM attr WHERE id_data IN ("); select_query.start_list(","); int last_data_id = -1; for (const auto& a: attrs) { if (a.id_data == last_data_id) continue; select_query.append_listf("%d", a.id_data); last_data_id = a.id_data; } select_query.append(") ORDER BY id_data, type"); // Get the current status of variables for this context auto sstm = conn.sqlitestatement(select_query); // Scan the result in parallel with the variable list, annotating changed // items with their data ID sql::bulk::AnnotateAttrsV6 todo(attrs); sstm->execute([&]() { todo.annotate( sstm->column_int(0), sstm->column_int(1), sstm->column_string(2)); }); todo.annotate_end(); // We now have a todo-list switch (update_mode) { case UPDATE: if (todo.do_update) { if (!ustm) ustm = conn.sqlitestatement("UPDATE attr SET value=? WHERE id_data=? AND type=?").release(); for (auto& v: attrs) { if (!v.needs_update()) continue; // Warning: we do not know if v.var is a string, so the result of // enqc is only valid until another enqc is called ustm->bind(v.attr->enqc(), v.id_data, v.attr->code()); ustm->execute(); v.set_updated(); } } break; case IGNORE: break; case ERROR: if (todo.do_update) throw error_consistency("refusing to overwrite existing data"); } if (todo.do_insert) { if (!istm) istm = conn.sqlitestatement("INSERT INTO attr (id_data, type, value) VALUES (?, ?, ?)").release(); for (auto& v: attrs) { if (!v.needs_insert()) continue; // Warning: we do not know if v.var is a string, so the result of // enqc is only valid until another enqc is called istm->bind(v.id_data, v.attr->code(), v.attr->enqc()); istm->execute(); v.set_inserted(); } } } void SQLiteAttrV6::dump(FILE* out) { int count = 0; fprintf(out, "dump of table attr:\n"); auto stm = conn.sqlitestatement("SELECT id_data, type, value FROM attr"); stm->execute([&]() { Varcode type = stm->column_int(1); fprintf(out, " %4d, %01d%02d%03d", stm->column_int(0), WR_VAR_F(type), WR_VAR_X(type), WR_VAR_Y(type)); if (stm->column_isnull(2)) fprintf(out, "\n"); else fprintf(out, " %s\n", stm->column_string(2)); ++count; }); fprintf(out, "%d element%s in table attr\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/sqlite/internals.cc0000644000175000017500000003025112652630043015154 00000000000000/* * db/sqlite/internals - Implementation infrastructure for the SQLite DB connection * * Copyright (C) 2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "internals.h" #include #include #include #include "dballe/core/vasprintf.h" #include "dballe/db/querybuf.h" #include #if 0 #include #include #include #include "dballe/core/verbose.h" #include #endif using namespace std; using namespace wreport; namespace dballe { namespace db { namespace { } error_sqlite::error_sqlite(sqlite3* db, const std::string& msg) { this->msg = msg; this->msg += ":"; this->msg += sqlite3_errmsg(db); } error_sqlite::error_sqlite(const std::string& dbmsg, const std::string& msg) { this->msg = msg; this->msg += ":"; this->msg += dbmsg; } void error_sqlite::throwf(sqlite3* db, const char* fmt, ...) { // Format the arguments va_list ap; va_start(ap, fmt); char* cmsg; vasprintf(&cmsg, fmt, ap); va_end(ap); // Convert to string std::string msg(cmsg); free(cmsg); throw error_sqlite(db, msg); } SQLiteConnection::SQLiteConnection() { } SQLiteConnection::~SQLiteConnection() { if (db) sqlite3_close(db); } void SQLiteConnection::open_file(const std::string& pathname, int flags) { url = "sqlite://" + pathname; int res = sqlite3_open_v2(pathname.c_str(), &db, flags, nullptr); if (res != SQLITE_OK) { // From http://www.sqlite.org/c3ref/open.html // Whether or not an error occurs when it is opened, resources // associated with the database connection handle should be // released by passing it to sqlite3_close() when it is no longer // required. std::string errmsg(sqlite3_errmsg(db)); sqlite3_close(db); db = nullptr; throw error_sqlite(errmsg, "opening " + pathname); } init_after_connect(); } void SQLiteConnection::open_memory(int flags) { url = "sqlite://:memory:"; open_file(":memory:", flags); } void SQLiteConnection::open_private_file(int flags) { url = "sqlite://"; open_file("", flags); } void SQLiteConnection::init_after_connect() { server_type = ServerType::SQLITE; // autocommit is off by default when inside a transaction // set_autocommit(false); exec("PRAGMA foreign_keys = ON"); if (getenv("DBA_INSECURE_SQLITE") != NULL) { exec("PRAGMA synchronous = OFF"); exec("PRAGMA journal_mode = OFF"); exec("PRAGMA legacy_file_format = 0"); } else { exec("PRAGMA journal_mode = MEMORY"); exec("PRAGMA legacy_file_format = 0"); } } void SQLiteConnection::exec(const std::string& query) { char* errmsg; int res = sqlite3_exec(db, query.c_str(), nullptr, nullptr, &errmsg); if (res != SQLITE_OK && errmsg) { // http://www.sqlite.org/c3ref/exec.html // // If the 5th parameter to sqlite3_exec() is not NULL then any error // message is written into memory obtained from sqlite3_malloc() and // passed back through the 5th parameter. To avoid memory leaks, the // application should invoke sqlite3_free() on error message strings // returned through the 5th parameter of of sqlite3_exec() after the // error message string is no longer needed.· std::string msg(errmsg); sqlite3_free(errmsg); throw error_sqlite(errmsg, "executing " + query); } } void SQLiteConnection::exec_nothrow(const std::string& query) noexcept { char* errmsg; int res = sqlite3_exec(db, query.c_str(), nullptr, nullptr, &errmsg); if (res != SQLITE_OK && errmsg) { // http://www.sqlite.org/c3ref/exec.html // // If the 5th parameter to sqlite3_exec() is not NULL then any error // message is written into memory obtained from sqlite3_malloc() and // passed back through the 5th parameter. To avoid memory leaks, the // application should invoke sqlite3_free() on error message strings // returned through the 5th parameter of of sqlite3_exec() after the // error message string is no longer needed.· fprintf(stderr, "cannot execute '%s': %s\n", query.c_str(), errmsg); sqlite3_free(errmsg); } } struct SQLiteTransaction : public Transaction { SQLiteConnection& conn; bool fired = false; SQLiteTransaction(SQLiteConnection& conn) : conn(conn) { } ~SQLiteTransaction() { if (!fired) rollback_nothrow(); } void commit() override { conn.exec("COMMIT"); fired = true; } void rollback() override { conn.exec("ROLLBACK"); fired = true; } void rollback_nothrow() { conn.exec_nothrow("ROLLBACK"); fired = true; } void lock_table(const char* name) override { // Nothing to do: SQLite locks the whole database, so table locking // is not needed } }; std::unique_ptr SQLiteConnection::transaction() { exec("BEGIN"); return unique_ptr(new SQLiteTransaction(*this)); } std::unique_ptr SQLiteConnection::sqlitestatement(const std::string& query) { return unique_ptr(new SQLiteStatement(*this, query)); } void SQLiteConnection::drop_table_if_exists(const char* name) { exec(string("DROP TABLE IF EXISTS ") + name); } int SQLiteConnection::get_last_insert_id() { int res = sqlite3_last_insert_rowid(db); if (res == 0) throw error_consistency("no last insert ID value returned from database"); return res; } bool SQLiteConnection::has_table(const std::string& name) { auto stm = sqlitestatement("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?"); stm->bind(name); bool found = false; int count = 0;; stm->execute_one([&]() { found = true; count += stm->column_int(0); }); return count > 0; } std::string SQLiteConnection::get_setting(const std::string& key) { if (!has_table("dballe_settings")) return string(); auto stm = sqlitestatement("SELECT value FROM dballe_settings WHERE \"key\"=?"); stm->bind(key); string res; stm->execute_one([&]() { res = stm->column_string(0); }); return res; } void SQLiteConnection::set_setting(const std::string& key, const std::string& value) { if (!has_table("dballe_settings")) exec("CREATE TABLE dballe_settings (\"key\" CHAR(64) NOT NULL PRIMARY KEY, value CHAR(64) NOT NULL)"); auto stm = sqlitestatement("INSERT OR REPLACE INTO dballe_settings (\"key\", value) VALUES (?, ?)"); stm->bind(key, value); stm->execute(); } void SQLiteConnection::drop_settings() { drop_table_if_exists("dballe_settings"); } int SQLiteConnection::changes() { return sqlite3_changes(db); } SQLiteStatement::SQLiteStatement(SQLiteConnection& conn, const std::string& query) : conn(conn) { // From http://www.sqlite.org/c3ref/prepare.html: // If the caller knows that the supplied string is nul-terminated, then // there is a small performance advantage to be gained by passing an nByte // parameter that is equal to the number of bytes in the input string // including the nul-terminator bytes as this saves SQLite from having to // make a copy of the input string. int res = sqlite3_prepare_v2(conn, query.c_str(), query.size() + 1, &stm, nullptr); if (res != SQLITE_OK) error_sqlite::throwf(conn, "cannot compile query '%s'", query.c_str()); } SQLiteStatement::~SQLiteStatement() { // Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. sqlite3_finalize(stm); } Datetime SQLiteStatement::column_datetime(int col) { Datetime res; string dt = column_string(col); sscanf(dt.c_str(), "%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu", &res.year, &res.month, &res.day, &res.hour, &res.minute, &res.second); return res; } void SQLiteStatement::execute(std::function on_row) { while (true) { switch (sqlite3_step(stm)) { case SQLITE_ROW: try { on_row(); } catch (...) { wrap_sqlite3_reset_nothrow(); throw; } break; case SQLITE_DONE: wrap_sqlite3_reset(); return; case SQLITE_BUSY: case SQLITE_MISUSE: default: reset_and_throw("cannot execute the query"); } } } void SQLiteStatement::execute_one(std::function on_row) { bool has_result = false; while (true) { switch (sqlite3_step(stm)) { case SQLITE_ROW: if (has_result) { wrap_sqlite3_reset(); throw error_consistency("query result has more than the one expected row"); } on_row(); has_result = true; break; case SQLITE_DONE: wrap_sqlite3_reset(); return; case SQLITE_BUSY: case SQLITE_MISUSE: default: reset_and_throw("cannot execute the query"); } } } void SQLiteStatement::execute() { while (true) { switch (sqlite3_step(stm)) { case SQLITE_ROW: case SQLITE_DONE: wrap_sqlite3_reset(); return; case SQLITE_BUSY: case SQLITE_MISUSE: default: reset_and_throw("cannot execute the query"); } } } void SQLiteStatement::bind_null_val(int idx) { if (sqlite3_bind_null(stm, idx) != SQLITE_OK) throw error_sqlite(conn, "cannot bind a NULL input column"); } void SQLiteStatement::bind_val(int idx, int val) { if (sqlite3_bind_int(stm, idx, val) != SQLITE_OK) throw error_sqlite(conn, "cannot bind an int input column"); } void SQLiteStatement::bind_val(int idx, unsigned val) { if (sqlite3_bind_int64(stm, idx, val) != SQLITE_OK) throw error_sqlite(conn, "cannot bind an int64 input column"); } void SQLiteStatement::bind_val(int idx, unsigned short val) { if (sqlite3_bind_int(stm, idx, val) != SQLITE_OK) throw error_sqlite(conn, "cannot bind an int input column"); } void SQLiteStatement::bind_val(int idx, const Datetime& val) { char* buf; int size = asprintf(&buf, "%04d-%02d-%02d %02d:%02d:%02d", val.year, val.month, val.day, val.hour, val.minute, val.second); if (sqlite3_bind_text(stm, idx, buf, size, free) != SQLITE_OK) throw error_sqlite(conn, "cannot bind a text (from Datetime) input column"); } void SQLiteStatement::bind_val(int idx, const char* val) { if (sqlite3_bind_text(stm, idx, val, -1, SQLITE_STATIC)) throw error_sqlite(conn, "cannot bind a text input column"); } void SQLiteStatement::bind_val(int idx, const std::string& val) { if (sqlite3_bind_text(stm, idx, val.data(), val.size(), SQLITE_STATIC)) throw error_sqlite(conn, "cannot bind a text input column"); } void SQLiteStatement::wrap_sqlite3_reset() { if (sqlite3_reset(stm) != SQLITE_OK) throw error_sqlite(conn, "cannot reset the query"); } void SQLiteStatement::wrap_sqlite3_reset_nothrow() noexcept { sqlite3_reset(stm); } void SQLiteStatement::reset_and_throw(const std::string& errmsg) { std::string sqlite_errmsg(sqlite3_errmsg(conn)); wrap_sqlite3_reset_nothrow(); throw error_sqlite(sqlite_errmsg, errmsg); } } } dballe-7.7/dballe/db/sqlite/station.h0000644000175000017500000000630712652630043014505 00000000000000/* * db/station - station table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQLITE_STATION_H #define DBALLE_DB_SQLITE_STATION_H /** @file * @ingroup db * * Station table management used by the db module. */ #include #include #include namespace wreport { struct Var; } namespace dballe { namespace db { struct SQLiteConnection; struct SQLiteStatement; namespace sqlite { /** * Precompiled queries to manipulate the station table */ class SQLiteStationBase : public sql::Station { protected: /** * DB connection. */ SQLiteConnection& conn; /** Precompiled select fixed station query */ SQLiteStatement* sfstm = nullptr; /** Precompiled select mobile station query */ SQLiteStatement* smstm = nullptr; /** Precompiled insert query */ SQLiteStatement* istm = nullptr; /// Lookup the ID of a station, returning true if it was found, false if not bool maybe_get_id(int lat, int lon, const char* ident, int* id); /// Run stm, read its output and generate variables to send to dest void read_station_vars(SQLiteStatement& stm, std::function)> dest); public: SQLiteStationBase(SQLiteConnection& conn); ~SQLiteStationBase(); SQLiteStationBase(const SQLiteStationBase&) = delete; SQLiteStationBase(const SQLiteStationBase&&) = delete; SQLiteStationBase& operator=(const SQLiteStationBase&) = delete; /** * Get the station ID given latitude, longitude and mobile identifier. * * It throws an exception if it does not exist. * * @return * Resulting ID of the station */ int get_id(int lat, int lon, const char* ident=nullptr) override; /** * Get the station ID given latitude, longitude and mobile identifier. * * It creates the station record if it does not exist. * * @return * Resulting ID of the station */ int obtain_id(int lat, int lon, const char* ident=nullptr, bool* inserted=NULL) override; void get_station_vars(int id_station, int id_report, std::function)> dest) override; void add_station_vars(int id_station, Record& rec) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; class SQLiteStationV6 : public SQLiteStationBase { public: SQLiteStationV6(SQLiteConnection& conn); }; } } } #endif dballe-7.7/dballe/db/sqlite/attrv6.h0000644000175000017500000000430412652630043014245 00000000000000/* * db/sqlite/attr - attribute table management * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQLITE_ATTRV6_H #define DBALLE_DB_SQLITE_ATTRV6_H #include #include namespace dballe { namespace db { namespace sqlite { /** * Precompiled queries to manipulate the attr table */ class SQLiteAttrV6 : public sql::AttrV6 { protected: /** DB connection. */ SQLiteConnection& conn; /// Precompiled select statement SQLiteStatement* sstm = nullptr; /// Precompiled insert statement SQLiteStatement* istm = nullptr; /// Precompiled update statement SQLiteStatement* ustm = nullptr; public: SQLiteAttrV6(SQLiteConnection& conn); SQLiteAttrV6(const SQLiteAttrV6&) = delete; SQLiteAttrV6(const SQLiteAttrV6&&) = delete; SQLiteAttrV6& operator=(const SQLiteAttrV6&) = delete; ~SQLiteAttrV6(); void insert(Transaction& t, sql::bulk::InsertAttrsV6& vars, UpdateMode update_mode=UPDATE) override; /** * Load from the database all the attributes for var * * @param var * wreport::Var to which the resulting attributes will be added * @return * The error indicator for the function (See @ref error.h) */ void read(int id_data, std::function)> dest) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/sqlite/datav6.h0000644000175000017500000000345612652630043014213 00000000000000/* * db/v6/data - data table management * * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_SQLITE_V6_DATA_H #define DBALLE_DB_SQLITE_V6_DATA_H /** @file * @ingroup db * * Data table management used by the db module. */ #include #include namespace dballe { struct Record; namespace db { namespace sqlite { struct DB; /** * Precompiled query to manipulate the data table */ class SQLiteDataV6 : public sql::DataV6 { protected: /// DB connection SQLiteConnection& conn; /// Precompiled select statement to prepare bulk insert SQLiteStatement* sstm = nullptr; public: SQLiteDataV6(SQLiteConnection& conn); SQLiteDataV6(const SQLiteDataV6&) = delete; SQLiteDataV6(const SQLiteDataV6&&) = delete; SQLiteDataV6& operator=(const SQLiteDataV6&) = delete; ~SQLiteDataV6(); void insert(Transaction& t, sql::bulk::InsertV6& vars, UpdateMode update_mode=UPDATE) override; void remove(const v6::QueryBuilder& qb) override; void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/mem/0000755000175000017500000000000012653425050012203 500000000000000dballe-7.7/dballe/db/mem/repinfo.cc0000644000175000017500000000732312652630043014100 00000000000000/* * db/mem/repinfo - repinfo table management * * Copyright (C) 2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "repinfo.h" #include "dballe/core/csv.h" #include "dballe/db/db.h" #include #include #include #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace mem { namespace { struct fd_closer { FILE* fd; fd_closer(FILE* fd) : fd(fd) {} ~fd_closer() { fclose(fd); } }; static inline void inplace_tolower(std::string& buf) { for (string::iterator i = buf.begin(); i != buf.end(); ++i) *i = tolower(*i); } } void Repinfo::load(const char* repinfo_file) { int added, deleted, updated; update(repinfo_file, &added, &deleted, &updated); } void Repinfo::update(const char* deffile, int* added, int* deleted, int* updated) { *added = *deleted = *updated = 0; if (deffile == 0) deffile = DB::default_repinfo_file(); // Open the input CSV file FILE* in = fopen(deffile, "r"); if (in == NULL) error_system::throwf("opening file %s", deffile); fd_closer closer(in); set oldkeys; for (map::const_iterator i = priorities.begin(); i != priorities.end(); ++i) oldkeys.insert(i->first); // Read the CSV file vector columns; for (int line = 1; csv_read_next(in, columns); ++line) { if (columns.size() != 6) error_parse::throwf(deffile, line, "Expected 6 columns, got %zd", columns.size()); // Lowercase all rep_memos inplace_tolower(columns[1]); string memo = columns[1]; int prio = strtol(columns[3].c_str(), 0, 10); map::iterator old = priorities.find(memo); if (old == priorities.end()) { priorities.insert(make_pair(memo, prio)); ++*added; } else { old->second = prio; ++*updated; } oldkeys.erase(memo); } for (set::const_iterator i = oldkeys.begin(); i != oldkeys.end(); ++i) { priorities.erase(*i); ++*deleted; } } std::map Repinfo::get_priorities() const { return priorities; } int Repinfo::get_prio(const std::string& memo) { string lc_memo = memo; inplace_tolower(lc_memo); std::map::const_iterator i = priorities.find(lc_memo); if (i != priorities.end()) return i->second; int max_prio = numeric_limits::min(); for (std::map::const_iterator i = priorities.begin(); i != priorities.end(); ++i) if (i->second > max_prio) max_prio = i->second; int new_prio = max_prio + 1; priorities.insert(make_pair(lc_memo, new_prio)); return new_prio; } void Repinfo::dump(FILE* out) const { for (std::map::const_iterator i = priorities.begin(); i != priorities.end(); ++i) fprintf(out, " %s: %d\n", i->first.c_str(), i->second); } } } } dballe-7.7/dballe/db/mem/cursor-test.cc0000644000175000017500000001142412652630043014725 00000000000000#include "db/tests.h" #include "db/mem/cursor.h" using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("basic", []() { using namespace dballe::db::mem::cursor; Memdb memdb; size_t v0 = memdb.insert(Coords(11, 45), "", "synop", Level(1), Trange(254), Datetime(2013, 11, 1, 12), newvar(WR_VAR(0, 12, 101), 15.0)); size_t vr = memdb.insert(Coords(11, 45), "", "temp", Level(1), Trange(254), Datetime(2013, 11, 1, 12), newvar(WR_VAR(0, 12, 101), 15.0)); size_t vm = memdb.insert(Coords(11, 45), "LH1234", "synop", Level(1), Trange(254), Datetime(2013, 11, 1, 12), newvar(WR_VAR(0, 12, 101), 15.0)); size_t vc = memdb.insert(Coords(11, 46), "", "synop", Level(1), Trange(254), Datetime(2013, 11, 1, 12), newvar(WR_VAR(0, 12, 101), 15.0)); size_t vd = memdb.insert(Coords(11, 45), "", "synop", Level(1), Trange(254), Datetime(2013, 11, 1, 13), newvar(WR_VAR(0, 12, 101), 15.0)); size_t vl = memdb.insert(Coords(11, 45), "", "synop", Level(2), Trange(254), Datetime(2013, 11, 1, 12), newvar(WR_VAR(0, 12, 101), 15.0)); size_t vt = memdb.insert(Coords(11, 45), "", "synop", Level(1), Trange(255), Datetime(2013, 11, 1, 12), newvar(WR_VAR(0, 12, 101), 15.0)); size_t vv = memdb.insert(Coords(11, 45), "", "synop", Level(1), Trange(254), Datetime(2013, 11, 1, 12), newvar(WR_VAR(0, 12, 102), 15.0)); DataBestKey k0(memdb.values, v0); DataBestKey km(memdb.values, vm); DataBestKey kc(memdb.values, vc); DataBestKey kr(memdb.values, vr); DataBestKey kl(memdb.values, vl); DataBestKey kt(memdb.values, vt); DataBestKey kd(memdb.values, vd); DataBestKey kv(memdb.values, vv); wassert(actual(k0 < k0).isfalse()); wassert(actual(k0 < kr).isfalse()); wassert(actual(k0) < kc); wassert(actual(k0) < km); wassert(actual(k0) < kd); wassert(actual(k0) < kl); wassert(actual(k0) < kt); wassert(actual(k0) < kv); // kr is the same as k0 wassert(actual(kr < k0).isfalse()); wassert(actual(kr < kr).isfalse()); wassert(actual(kr) < kc); wassert(actual(kr) < km); wassert(actual(kr) < kd); wassert(actual(kr) < kl); wassert(actual(kr) < kt); wassert(actual(kr) < kv); wassert(actual(km < k0).isfalse()); wassert(actual(km < kr).isfalse()); wassert(actual(km) < kc); wassert(actual(km < km).isfalse()); wassert(actual(km < kd).isfalse()); wassert(actual(km < kl).isfalse()); wassert(actual(km < kt).isfalse()); wassert(actual(km < kv).isfalse()); wassert(actual(kc < k0).isfalse()); wassert(actual(kc < kr).isfalse()); wassert(actual(kc < kc).isfalse()); wassert(actual(kc < km).isfalse()); wassert(actual(kc < kd).isfalse()); wassert(actual(kc < kl).isfalse()); wassert(actual(kc < kt).isfalse()); wassert(actual(kc < kv).isfalse()); wassert(actual(kd < k0).isfalse()); wassert(actual(kd < kr).isfalse()); wassert(actual(kd) < kc); wassert(actual(kd) < km); wassert(actual(kd < kd).isfalse()); wassert(actual(kd < kl).isfalse()); wassert(actual(kd < kt).isfalse()); wassert(actual(kd < kv).isfalse()); wassert(actual(kl < k0).isfalse()); wassert(actual(kl < kr).isfalse()); wassert(actual(kl) < kc); wassert(actual(kl) < km); wassert(actual(kl) < kd); wassert(actual(kl < kl).isfalse()); wassert(actual(kl < kt).isfalse()); wassert(actual(kl < kv).isfalse()); wassert(actual(kt < k0).isfalse()); wassert(actual(kt < kr).isfalse()); wassert(actual(kt) < kc); wassert(actual(kt) < km); wassert(actual(kt) < kd); wassert(actual(kt) < kl); wassert(actual(kt < kt).isfalse()); wassert(actual(kt < kv).isfalse()); wassert(actual(kv < k0).isfalse()); wassert(actual(kv < kr).isfalse()); wassert(actual(kv) < kc); wassert(actual(kv) < km); wassert(actual(kv) < kd); wassert(actual(kv) < kl); wassert(actual(kv) < kt); wassert(actual(kv < kv).isfalse()); }); } } test("dbmem_cursor"); } dballe-7.7/dballe/db/mem/repinfo.h0000644000175000017500000000424512652630043013742 00000000000000/* * db/mem/repinfo - repinfo priority tracking * * Copyright (C) 2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_MEM_REPINFO_H #define DBALLE_DB_MEM_REPINFO_H #include #include #include namespace dballe { namespace db { namespace mem { class Repinfo { protected: std::map priorities; public: /// Get the priority for a rep_memo int get_prio(const std::string& memo); /// Like update, but it ignores the added, delete and updated stats void load(const char* repinfo_file=0); /** * Update the report type information in the database using the data from the * given file. * * @param ri * dba_db_repinfo used to update the database * @param deffile * Pathname of the file to use for the update. The NULL value is accepted * and means to use the default configure repinfo.csv file. * @retval added * Number of entries that have been added during the update. * @retval deleted * Number of entries that have been deleted during the update. * @retval updated * Number of entries that have been updated during the update. */ void update(const char* deffile, int* added, int* deleted, int* updated); /** * Get a mapping between rep_memo and their priorities */ std::map get_priorities() const; /// Dump contents to a file void dump(FILE* out) const; }; } } } #endif dballe-7.7/dballe/db/mem/repinfo-test.cc0000644000175000017500000000513712652630043015056 00000000000000#include "db/tests.h" #include "db/mem/db.h" #include "db/mem/repinfo.h" using namespace dballe; using namespace dballe::db::mem; using namespace dballe::tests; using namespace std; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("prio", []() { Repinfo ri; ri.load(); wassert(actual(ri.get_prio("synop")) == 101); wassert(actual(ri.get_prio("generic")) == 1000); }); add_method("update", []() { Repinfo ri; ri.load(); wassert(actual(ri.get_prio("synop")) == 101); int added, deleted, updated; ri.update(NULL, &added, &deleted, &updated); wassert(actual(added) == 0); wassert(actual(deleted) == 0); wassert(actual(updated) == 13); wassert(actual(ri.get_prio("synop")) == 101); }); add_method("update_regression", []() { // Test update from a file that was known to fail Repinfo ri; ri.load(); wassert(actual(ri.get_prio("synop")) == 101); int added, deleted, updated; ri.update((string(getenv("DBA_TESTDATA")) + "/test-repinfo1.csv").c_str(), &added, &deleted, &updated); wassert(actual(added) == 3); wassert(actual(deleted) == 11); wassert(actual(updated) == 2); wassert(actual(ri.get_prio("synop")) == 101); wassert(actual(ri.get_prio("FIXspnpo")) == 200); }); add_method("update_negative_prio", []() { // Test update from a file with a negative priority Repinfo ri; ri.load(); wassert(actual(ri.get_prio("generic")) == 1000); int added, deleted, updated; ri.update((string(getenv("DBA_TESTDATA")) + "/test-repinfo2.csv").c_str(), &added, &deleted, &updated); wassert(actual(added) == 3); wassert(actual(deleted) == 11); wassert(actual(updated) == 2); wassert(actual(ri.get_prio("generic")) == -5); }); add_method("autocreate", []() { // Test automatic repinfo creation Repinfo ri; ri.load(); wassert(actual(ri.get_prio("foobar")) == 1001); wassert(actual(ri.get_prio("foobar")) == 1001); wassert(actual(ri.get_prio("barbaz")) == 1002); wassert(actual(ri.get_prio("barbaz")) == 1002); wassert(actual(ri.get_prio("foobar")) == 1001); }); } } test("mem_repinfo"); } dballe-7.7/dballe/db/mem/db.cc0000644000175000017500000003654612652630043013034 00000000000000#include "db.h" #include "cursor.h" #include "dballe/msg/msg.h" #include "dballe/msg/context.h" #include "dballe/core/varmatch.h" #include "dballe/core/record.h" #include "dballe/core/query.h" #include "dballe/core/values.h" #include "dballe/core/defs.h" #include "dballe/memdb/results.h" #include "dballe/memdb/serializer.h" #include #include // #define TRACE_SOURCE #include "dballe/core/trace.h" using namespace dballe::memdb; using namespace std; using namespace wreport; namespace dballe { namespace db { namespace mem { DB::DB() {} DB::DB(const std::string& arg) : serialization_dir(arg) { if (!serialization_dir.empty()) { serialize::CSVReader reader(serialization_dir, memdb); reader.read(); } } DB::~DB() { if (!serialization_dir.empty()) { serialize::CSVWriter writer(serialization_dir); writer.write(memdb); writer.commit(); } } void DB::disappear() { memdb.clear(); } void DB::reset(const char* repinfo_file) { disappear(); repinfo.load(repinfo_file); } void DB::update_repinfo(const char* repinfo_file, int* added, int* deleted, int* updated) { repinfo.update(repinfo_file, added, deleted, updated); } std::map DB::get_repinfo_priorities() { return repinfo.get_priorities(); } void DB::insert_station_data(StationValues& vals, bool can_replace, bool station_can_add) { // Obtain the station vals.info.ana_id = memdb.stations.obtain(vals.info, station_can_add); const memdb::Station& station = *memdb.stations[vals.info.ana_id]; // Insert all the variables we find for (auto& i: vals.values) i.second.data_id = memdb.stationvalues.insert(station, *i.second.var, can_replace); } void DB::insert_data(DataValues& vals, bool can_replace, bool station_can_add) { // Obtain the station vals.info.ana_id = memdb.stations.obtain(vals.info, station_can_add); const memdb::Station& station = *memdb.stations[vals.info.ana_id]; // Obtain the levtr const LevTr& levtr = *memdb.levtrs[memdb.levtrs.obtain(vals.info.level, vals.info.trange)]; // Insert all the variables we find for (auto& i: vals.values) i.second.data_id = memdb.values.insert(station, levtr, vals.info.datetime, *i.second.var, can_replace); } void DB::remove_station_data(const Query& query) { Results res(memdb.stationvalues); raw_query_station_data(core::Query::downcast(query), res); memdb.remove(res); } void DB::remove(const Query& query) { Results res(memdb.values); raw_query_data(core::Query::downcast(query), res); memdb.remove(res); } void DB::remove_all() { memdb.clear(); } void DB::vacuum() { // Nothing to do } namespace { struct MatchAnaFilter : public Match { const memdb::StationValues& stationvalues; Varmatch* match; MatchAnaFilter(const memdb::StationValues& stationvalues, const std::string& expr) : stationvalues(stationvalues), match(Varmatch::parse(expr).release()) {} ~MatchAnaFilter() { delete match; } bool operator()(const memdb::Station& val) const override { const memdb::StationValue* sv = stationvalues.get(val, match->code); if (!sv) return false; return (*match)(*(sv->var)); } private: MatchAnaFilter(const MatchAnaFilter&); MatchAnaFilter& operator=(const MatchAnaFilter&); }; struct MatchRepinfo : public Match { std::set report_whitelist; bool operator()(const memdb::Station& val) const override { return report_whitelist.find(val.report) != report_whitelist.end(); } }; } void DB::raw_query_stations(const core::Query& q, memdb::Results& res) { // Build a matcher for queries by priority const int& priomin = q.prio_min; const int& priomax = q.prio_max; if (priomin != MISSING_INT || priomax != MISSING_INT) { // If priomax == priomin, use exact prio instead of // min-max bounds if (priomax == priomin) { std::map prios = get_repinfo_priorities(); unique_ptr m(new MatchRepinfo); for (std::map::const_iterator i = prios.begin(); i != prios.end(); ++i) if (i->second == priomin) m->report_whitelist.insert(i->first); res.add(m.release()); } else { // Here, prio is unset and priomin != priomax // Deal with priomin > priomax if (priomin != MISSING_INT && priomax != MISSING_INT && priomax < priomin) { res.set_to_empty(); return; } std::map prios = get_repinfo_priorities(); unique_ptr m(new MatchRepinfo); for (std::map::const_iterator i = prios.begin(); i != prios.end(); ++i) { if (priomin != MISSING_INT && i->second < priomin) continue; if (priomax != MISSING_INT && i->second > priomax) continue; m->report_whitelist.insert(i->first); } res.add(m.release()); } } if (!q.ana_filter.empty()) { res.add(new MatchAnaFilter(memdb.stationvalues, q.ana_filter)); trace_query("Found ana filter %s\n", val); } if (q.block != MISSING_INT) { char query[100]; snprintf(query, 100, "B01001=%d", q.block); res.add(new MatchAnaFilter(memdb.stationvalues, query)); trace_query("Found block filter %s\n", query); } if (q.station != MISSING_INT) { char query[100]; snprintf(query, 100, "B01002=%d", q.station); res.add(new MatchAnaFilter(memdb.stationvalues, query)); trace_query("Found station filter %s\n", query); } memdb.stations.query(q, res); } void DB::raw_query_station_data(const core::Query& q, memdb::Results& res) { // Get a list of stations we can match Results res_st(memdb.stations); raw_query_stations(q, res_st); memdb.stationvalues.query(q, res_st, res); } void DB::raw_query_data(const core::Query& q, memdb::Results& res) { // Get a list of stations we can match Results res_st(memdb.stations); raw_query_stations(q, res_st); // Get a list of stations we can match Results res_tr(memdb.levtrs); memdb.levtrs.query(q, res_tr); // Query variables memdb.values.query(q, res_st, res_tr, res); } std::unique_ptr DB::query_stations(const Query& query) { const core::Query& q = core::Query::downcast(query); unsigned int modifiers = q.get_modifiers(); Results res(memdb.stations); // Build var/varlist special-cased filter for station queries if (!q.varcodes.empty()) { const set& varcodes = q.varcodes; // Iterate all the possible values, taking note of the stations for // variables whose varcodes are in 'varcodes' unique_ptr> id_whitelist(new set); for (ValueStorage::index_iterator i = memdb.values.index_begin(); i != memdb.values.index_end(); ++i) { const Value& v = *memdb.values[*i]; if (varcodes.find(v.var->code()) != varcodes.end()) id_whitelist->insert(*i); } IF_TRACE_QUERY { trace_query("Found var/varlist station filter: %zd items in id whitelist:", id_whitelist->size()); for (set::const_iterator i = id_whitelist->begin(); i != id_whitelist->end(); ++i) trace_query(" %zd", *i); trace_query("\n"); } res.add_set(move(id_whitelist)); } raw_query_stations(q, res); return cursor::createStations(*this, modifiers, res); } std::unique_ptr DB::query_station_data(const Query& query) { const core::Query& q = core::Query::downcast(query); unsigned int modifiers = q.get_modifiers(); if (modifiers & DBA_DB_MODIFIER_BEST) { throw error_unimplemented("best queries of station vars"); #warning TODO } else { Results res(memdb.stationvalues); raw_query_station_data(q, res); return cursor::createStationData(*this, modifiers, res); } } std::unique_ptr DB::query_data(const Query& query) { const core::Query& q = core::Query::downcast(query); unsigned int modifiers = q.get_modifiers(); Results res(memdb.values); raw_query_data(q, res); if (modifiers & DBA_DB_MODIFIER_BEST) { return cursor::createDataBest(*this, modifiers, res); } else { return cursor::createData(*this, modifiers, res); } } std::unique_ptr DB::query_summary(const Query& query) { const core::Query& q = core::Query::downcast(query); unsigned int modifiers = q.get_modifiers(); Results res(memdb.values); raw_query_data(q, res); return cursor::createSummary(*this, modifiers, res); } void DB::attr_query_station(int data_id, std::function)>&& dest) { ValueBase* v = memdb.stationvalues.get_checked(data_id); if (!v) error_notfound::throwf("no station variable found with data id %d", data_id); v->query_attrs(dest); } void DB::attr_query_data(int data_id, std::function)>&& dest) { ValueBase* v = memdb.values.get_checked(data_id); if (!v) error_notfound::throwf("no data variable found with data id %d", data_id); v->query_attrs(dest); } void DB::attr_insert_station(int data_id, const Values& attrs) { ValueBase* v = memdb.stationvalues.get_checked(data_id); if (!v) error_notfound::throwf("no station variable found with data id %d", data_id); v->attr_insert(attrs); } void DB::attr_insert_data(int data_id, const Values& attrs) { ValueBase* v = memdb.values.get_checked(data_id); if (!v) error_notfound::throwf("no data variable found with data id %d", data_id); v->attr_insert(attrs); } void DB::attr_remove_station(int data_id, const db::AttrList& qcs) { ValueBase* v = memdb.stationvalues.get_checked(data_id); if (!v) error_notfound::throwf("no station variable found with data id %d", data_id); v->attr_remove(qcs); } void DB::attr_remove_data(int data_id, const db::AttrList& qcs) { ValueBase* v = memdb.values.get_checked(data_id); if (!v) error_notfound::throwf("no data variable found with data id %d", data_id); v->attr_remove(qcs); } bool DB::is_station_variable(int data_id, wreport::Varcode varcode) { // FIXME: this is hackish, and has unexpected results if we have data // values and station values with the same id_var and id_data. Giving that // measured values are usually different than the station values, the case // should be rare enough that we can work around the issue in this way // rather than breaking the Fortran API. ValueBase* v = memdb.values.get_checked(data_id); if (v && v->var->code() == varcode) return false; v = memdb.stationvalues.get_checked(data_id); if (v && v->var->code() == varcode) return true; error_notfound::throwf("variable B%02d%03d not found at data id %d", WR_VAR_X(varcode), WR_VAR_Y(varcode), data_id); } void DB::dump(FILE* out) { fprintf(out, "repinfo data:\n"); repinfo.dump(out); memdb.dump(out); } void DB::import_msg(const Message& msg, const char* repmemo, int flags) { memdb.insert(Msg::downcast(msg), flags | DBA_IMPORT_OVERWRITE, flags | DBA_IMPORT_FULL_PSEUDOANA, flags | DBA_IMPORT_ATTRS, repmemo); } namespace { struct CompareForExport { // Return an inverse comparison, so that the priority queue gives us the // smallest items first bool operator() (const Value* x, const Value* y) const { // Compare station and report if (x->station.id < y->station.id) return false; if (x->station.id > y->station.id) return true; // Compare datetime return x->datetime > y->datetime; } }; } bool DB::export_msgs(const Query& query_gen, std::function&&)> dest) { const core::Query& query = core::Query::downcast(query_gen); Results res(memdb.values); raw_query_data(query, res); // Sorted value IDs priority_queue, CompareForExport> values; res.copy_valptrs_to(stl::pusher(values)); TRACE("export_msgs: %zd values in priority queue\n", values.size()); // Message being built unique_ptr msg; // Last value seen, used to detect when we can move on to the next message const Value* old_val = 0; // Iterate all results, sorted for ( ; !values.empty(); values.pop()) { const Value* val = values.top(); TRACE("Got %zd %04d-%02d-%02d %02d:%02d:%02d B%02d%03d %d,%d, %d,%d %d,%d,%d %s\n", val->station.id, (int)val->datetime.date.year, (int)val->datetime.date.month, (int)val->datetime.date.day, (int)val->datetime.time.hour, (int)val->datetime.time.minute, (int)val->datetime.time.second, WR_VAR_X(val->var->code()), WR_VAR_Y(val->var->code()), val->levtr.level.ltype1, val->levtr.level.l1, val->levtr.level.ltype2, val->levtr.level.l2, val->levtr.trange.pind, val->levtr.trange.p1, val->levtr.trange.p2, val->var->value()); // See if we have the start of a new message if (!old_val || old_val->station.id != val->station.id || old_val->datetime != val->datetime) { // Flush current message TRACE("New message\n"); if (msg.get() != NULL) { //TRACE("Sending old message to consumer\n"); if (msg->type == MSG_PILOT || msg->type == MSG_TEMP || msg->type == MSG_TEMP_SHIP) { unique_ptr copy(new Msg); msg->sounding_pack_levels(*copy); if (!dest(move(copy))) return false; } else if (!dest(move(msg))) return false; } // Start writing a new message msg.reset(new Msg); // Fill datetime msg->set_datetime(val->datetime); // Fill station info msg::Context& c_st = val->station.fill_msg(*msg); // Fill station vars memdb.stationvalues.fill_msg(val->station, c_st); // Update last value seen info old_val = val; } TRACE("Inserting var B%02d%03d (%s)\n", WR_VAR_X(val->var->code()), WR_VAR_Y(val->var->code()), val->var->value()); msg::Context& ctx = msg->obtain_context(val->levtr.level, val->levtr.trange); ctx.set(*val->var); } if (msg.get() != NULL) { TRACE("Inserting leftover old message\n"); if (msg->type == MSG_PILOT || msg->type == MSG_TEMP || msg->type == MSG_TEMP_SHIP) { unique_ptr copy(new Msg); msg->sounding_pack_levels(*copy); if (!dest(move(copy))) return false; } else if (!dest(move(msg))) return false; } return true; } } } } #include "dballe/memdb/results.tcc" /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/db/mem/cursor.cc0000644000175000017500000005212612652630043013754 00000000000000#include "cursor.h" #include "db.h" #include "dballe/core/record.h" #include "dballe/core/query.h" #include #include #include using namespace std; using namespace wreport; using namespace dballe::memdb; namespace dballe { namespace db { namespace mem { namespace cursor { namespace { /** * Structure used to build and execute a query, and to iterate through the * results */ template class Base : public Interface { protected: /// Database to operate on mem::DB& db; /// Modifier flags to enable special query behaviours const unsigned int modifiers; /// Number of results still to be fetched size_t count = 0; public: virtual ~Base() {} dballe::DB& get_db() const override { return db; } int remaining() const override { return count; } /** * Get a new item from the results of a query * * @returns * true if a new record has been read, false if there is no more data to read */ bool next() override = 0; /// Discard the results that have not been read yet void discard_rest() override = 0; #if 0 /** * Iterate the cursor until the end, returning the number of items. * * If dump is a FILE pointer, also dump the cursor values to it */ virtual unsigned test_iterate(FILE* dump=0) = 0; #endif protected: /** * Create a query cursor * * @param wanted * The values wanted in output * @param modifiers * Optional modifiers to ask for special query behaviours */ Base(mem::DB& db, unsigned modifiers) : db(db), modifiers(modifiers) { } void to_record_station(const memdb::Station& st, Record& rec) { rec.set("ana_id", (int)st.id); core::Record::downcast(rec).set_coords(st.coords); if (st.mobile) { rec.set("ident", st.ident); rec.set("mobile", 1); } else { rec.unset("ident"); rec.set("mobile", 0); } rec.set("rep_memo", st.report); rec.set("priority", db.repinfo.get_prio(st.report)); } void to_record_levtr(const memdb::Value& val, Record& rec) { rec.set(val.levtr.level); rec.set(val.levtr.trange); } void to_record_varcode(wreport::Varcode code, Record& rec) { char bname[7]; snprintf(bname, 7, "B%02d%03d", WR_VAR_X(code), WR_VAR_Y(code)); rec.setc("var", bname); } void to_record_value(const memdb::Value& val, Record& rec) { to_record_levtr(val, rec); rec.set(val.datetime); to_record_varcode(val.var->code(), rec); rec.set(*val.var); } /// Query extra station info and add it to \a rec void add_station_info(const memdb::Station& st, Record& rec) { db.memdb.stationvalues.fill_record(st, rec); } }; /** * Implement next() for cursors that can be implemented on top of a sorted * collection offering size(), empty(), pop() and top() */ template struct CursorSorted : public Base { typename SortedResults::value_type cur; SortedResults results; bool first = true; bool next() override { if (this->count == 0 || results.empty()) return false; if (first) first = false; else results.pop(); --(this->count); if (results.empty()) return false; this->cur = results.top(); return true; } void discard_rest() override { // We cannot call results.clear() // FIXME: we can probably get rid of discard_rest() and do proper // review and destructor work. This is only used to flush DB cursors to // avoid shutting down a partial query for some databases. But really, // is it needed at all? this->count = 0; } template CursorSorted(mem::DB& db, unsigned modifiers, T& res) : Base(db, modifiers), results(db, res) { this->count = results.size(); } }; struct StationResultQueue : public stack { StationResultQueue(DB&, Results& res) { res.copy_valptrs_to(stl::pusher(*this)); } }; struct MemCursorStations : public CursorSorted { MemCursorStations(mem::DB& db, unsigned modifiers, Results& res) : CursorSorted(db, modifiers, res) { } int get_station_id() const override { return cur->id; } double get_lat() const override { return cur->coords.dlat(); } double get_lon() const override { return cur->coords.dlon(); } const char* get_ident(const char* def=0) const override { if (cur->mobile) return cur->ident.c_str(); else return def; } const char* get_rep_memo() const override { return cur->report.c_str(); } void to_record(Record& rec) { this->to_record_station(*cur, rec); this->add_station_info(*cur, rec); } }; struct CompareStationData { const ValueStorage& values; CompareStationData(const ValueStorage& values) : values(values) {} // Return an inverse comparison, so that the priority queue gives us the // smallest items first bool operator() (size_t ix, size_t iy) const { const memdb::StationValue& x = *values[ix]; const memdb::StationValue& y = *values[iy]; if (int res = x.station.coords.compare(y.station.coords)) return res > 0; if (x.station.ident < y.station.ident) return false; if (x.station.ident > y.station.ident) return true; if (int res = x.var->code() - y.var->code()) return res > 0; return x.station.report > y.station.report; } }; struct StationValueResultQueue : public priority_queue, CompareStationData> { StationValueResultQueue(DB&, Results& res) : priority_queue, CompareStationData>(CompareStationData(res.values)) { res.copy_indices_to(stl::pusher(*this)); } }; struct MemCursorStationData : public CursorSorted { const ValueStorage& values; MemCursorStationData(mem::DB& db, unsigned modifiers, Results& res) : CursorSorted(db, modifiers, res), values(res.values) { } int get_station_id() const override { return values[cur]->station.id; } double get_lat() const override { return values[cur]->station.coords.dlat(); } double get_lon() const override { return values[cur]->station.coords.dlon(); } const char* get_ident(const char* def=0) const override { if (values[cur]->station.mobile) return values[cur]->station.ident.c_str(); else return def; } const char* get_rep_memo() const override { return values[cur]->station.report.c_str(); } wreport::Varcode get_varcode() const override { return values[this->cur]->var->code(); } wreport::Var get_var() const override { Var res(values[this->cur]->var->info()); res.setval(*values[this->cur]->var); return res; } int attr_reference_id() const override { return this->cur; } #if 0 void query_attrs(function&&)> dest) override { queue.top()->query_attrs(dest); } virtual void attr_insert(const Values& attrs) { queue.top()->attr_insert(attrs); } virtual void attr_remove(const AttrList& qcs) { queue.top()->attr_remove(qcs); } #endif void to_record(Record& rec) { to_record_station(values[cur]->station, rec); to_record_varcode(values[cur]->var->code(), rec); rec.set(*values[cur]->var); } }; struct CompareData { const ValueStorage& values; CompareData(const ValueStorage& values) : values(values) {} // Return an inverse comparison, so that the priority queue gives us the // smallest items first bool operator() (size_t x, size_t y) const { const memdb::Value& vx = *values[x]; const memdb::Value& vy = *values[y]; if (int res = vx.station.coords.compare(vy.station.coords)) return res > 0; if (vx.station.ident < vy.station.ident) return false; if (vx.station.ident > vy.station.ident) return true; if (int res = vx.datetime.compare(vy.datetime)) return res > 0; if (int res = vx.levtr.level.compare(vy.levtr.level)) return res > 0; if (int res = vx.levtr.trange.compare(vy.levtr.trange)) return res > 0; if (vx.station.report < vy.station.report) return false; if (vx.station.report > vy.station.report) return true; if (int res = vx.var->code() - vy.var->code()) return res > 0; return 0; } }; struct DataResultQueue : public priority_queue, CompareData> { DataResultQueue(DB&, Results& res) : priority_queue, CompareData>(CompareData(res.values)) { res.copy_indices_to(stl::pusher(*this)); } }; struct DataBestResultQueue : public map { typedef size_t value_type; const ValueStorage& values; std::map prios; DataBestResultQueue(DB& db, Results& res) : values(res.values), prios(db.get_repinfo_priorities()) { res.copy_indices_to(stl::pusher(*this)); } void dump(FILE* out) const { for (const_iterator i = begin(); i != end(); ++i) { const memdb::Value& k = i->first.value(); const memdb::Value& v = *values[i->second]; stringstream buf; buf << k.station.coords << "\t" << k.station.ident << "\t" << k.levtr.level << "\t" << k.levtr.trange << "\t" << k.datetime << ": " << v.station.report << "\t"; v.var->print_without_attrs(buf); fputs(buf.str().c_str(), out); } } /** * Add val to the map, but in case of conflict it only keeps the value with * the highest priority. */ void push(size_t val) { iterator i = find(DataBestKey(values, val)); if (i == end()) insert(make_pair(DataBestKey(values, val), val)); else { const memdb::Value& vx = *values[i->second]; const memdb::Value& vy = *values[val]; if (prios[vx.station.report] < prios[vy.station.report]) i->second = val; } } size_t top() const { return begin()->second; } void pop() { erase(begin()); } }; template struct CursorDataBase : public CursorSorted { const ValueStorage& values; CursorDataBase(mem::DB& db, unsigned modifiers, Results& res) : CursorSorted(db, modifiers, res), values(res.values) { } int get_station_id() const override { return values[this->cur]->station.id; } double get_lat() const override { return values[this->cur]->station.coords.dlat(); } double get_lon() const override { return values[this->cur]->station.coords.dlon(); } const char* get_ident(const char* def=0) const override { if (values[this->cur]->station.mobile) return values[this->cur]->station.ident.c_str(); else return def; } const char* get_rep_memo() const override { return values[this->cur]->station.report.c_str(); } Level get_level() const override { return values[this->cur]->levtr.level; } Trange get_trange() const override { return values[this->cur]->levtr.trange; } wreport::Varcode get_varcode() const override { return values[this->cur]->var->code(); } Datetime get_datetime() const override { return values[this->cur]->datetime; } wreport::Var get_var() const override { Var res(values[this->cur]->var->info()); res.setval(*values[this->cur]->var); return res; } int attr_reference_id() const override { return this->cur; } #if 0 void attr_insert(const Values& attrs) override { this->values[this->cur_idx]->attr_insert(attrs); } void attr_remove(const AttrList& qcs) override { this->values[this->cur_idx]->attr_remove(qcs); } void query_attrs(function&&)> dest) override { this->cur_value->query_attrs(dest); } #endif void to_record(Record& rec) override { this->to_record_station(values[this->cur]->station, rec); rec.clear_vars(); this->to_record_value(*values[this->cur], rec); rec.seti("context_id", this->cur); } }; struct MemCursorData : public CursorDataBase { MemCursorData(mem::DB& db, unsigned modifiers, Results& res) : CursorDataBase(db, modifiers, res) { } }; struct MemCursorDataBest : public CursorDataBase { MemCursorDataBest(mem::DB& db, unsigned modifiers, Results& res) : CursorDataBase(db, modifiers, res) { } }; struct MemCursorSummary : public Base { memdb::Summary values; memdb::Summary::const_iterator iter_cur; memdb::Summary::const_iterator iter_end; bool first; MemCursorSummary(mem::DB& db, unsigned modifiers, Results& res) : Base(db, modifiers), first(true) { memdb::Summarizer summarizer(values); res.copy_valptrs_to(stl::trivial_inserter(summarizer)); // Start iterating at the beginning iter_cur = values.begin(); iter_end = values.end(); // Initialize the result count count = values.size(); } int get_station_id() const override { return iter_cur->first.sample.station.id; } double get_lat() const override { return iter_cur->first.sample.station.coords.dlat(); } double get_lon() const override { return iter_cur->first.sample.station.coords.dlon(); } const char* get_ident(const char* def=0) const override { if (iter_cur->first.sample.station.mobile) return iter_cur->first.sample.station.ident.c_str(); else return def; } const char* get_rep_memo() const override { return iter_cur->first.sample.station.report.c_str(); } Level get_level() const override { return iter_cur->first.sample.levtr.level; } Trange get_trange() const override { return iter_cur->first.sample.levtr.trange; } wreport::Varcode get_varcode() const override { return iter_cur->first.sample.var->code(); } DatetimeRange get_datetimerange() const override { return DatetimeRange(iter_cur->second.dtmin, iter_cur->second.dtmax); } size_t get_count() const override { return iter_cur->second.count; } bool next() { if (iter_cur == iter_end) return false; if (first) first = false; else ++iter_cur; --count; if (iter_cur != iter_end) { #if 0 cur_value = &(iter_cur->first.sample); cur_var = cur_value->var; cur_station = &(iter_cur->first.sample.station); #endif return true; } return false; } void discard_rest() { iter_cur = iter_end; count = 0; } void to_record(Record& rec) { to_record_station(iter_cur->first.sample.station, rec); to_record_levtr(iter_cur->first.sample, rec); to_record_varcode(iter_cur->first.sample.var->code(), rec); if (modifiers & DBA_DB_MODIFIER_SUMMARY_DETAILS) { rec.set(get_datetimerange()); rec.seti("context_id", get_count()); } } }; } unique_ptr createStations(mem::DB& db, unsigned modifiers, Results& res) { return unique_ptr(new MemCursorStations(db, modifiers, res)); } unique_ptr createStationData(mem::DB& db, unsigned modifiers, Results& res) { return unique_ptr(new MemCursorStationData(db, modifiers, res)); } unique_ptr createData(mem::DB& db, unsigned modifiers, Results& res) { return unique_ptr(new MemCursorData(db, modifiers, res)); } unique_ptr createDataBest(mem::DB& db, unsigned modifiers, Results& res) { return unique_ptr(new MemCursorDataBest(db, modifiers, res)); } unique_ptr createSummary(mem::DB& db, unsigned modifiers, Results& res) { return unique_ptr(new MemCursorSummary(db, modifiers, res)); } DataBestKey::DataBestKey(const memdb::ValueStorage& values, size_t idx) : values(values), idx(idx) {} bool DataBestKey::operator<(const DataBestKey& o) const { // Normal sort here, but we ignore report so that two values which only // differ in report are considered the same const memdb::Value& vx = value(); const memdb::Value& vy = o.value(); if (int res = vx.station.coords.compare(vy.station.coords)) return res < 0; if (vx.station.ident < vy.station.ident) return true; if (vx.station.ident > vy.station.ident) return false; if (int res = vx.datetime.compare(vy.datetime)) return res < 0; if (int res = vx.levtr.level.compare(vy.levtr.level)) return res < 0; if (int res = vx.levtr.trange.compare(vy.levtr.trange)) return res < 0; if (int res = vx.var->code() - vy.var->code()) return res < 0; // They are the same return false; } std::ostream& operator<<(std::ostream& out, const DataBestKey& k) { const memdb::Value& v = k.value(); out << v.station.coords << "." << v.station.ident << ":" << v.levtr.level << ":" << v.levtr.trange << ":" << v.datetime << ":" << varcode_format(v.var->code()); return out; } #if 0 unsigned CursorStations::test_iterate(FILE* dump) { Record r; unsigned count; for (count = 0; next(); ++count) { if (dump) { to_record(r); fprintf(dump, "%02d %02.4f %02.4f %-10s\n", r.get(DBA_KEY_ANA_ID, -1), r.get(DBA_KEY_LAT, 0.0), r.get(DBA_KEY_LON, 0.0), r.get(DBA_KEY_IDENT, "")); } } return count; } unsigned CursorData::test_iterate(FILE* dump) { Record r; unsigned count; for (count = 0; next(); ++count) { if (dump) { /* to_record(r); fprintf(dump, "%02d %06d %06d %-10s\n", r.get(DBA_KEY_ANA_ID, -1), r.get(DBA_KEY_LAT, 0.0), r.get(DBA_KEY_LON, 0.0), r.get(DBA_KEY_IDENT, "")); */ } } return count; } void CursorSummary::to_record(Record& rec) { to_record_pseudoana(rec); to_record_repinfo(rec); //rec.key(DBA_KEY_CONTEXT_ID).seti(sqlrec.out_id_data); to_record_varcode(rec); to_record_ltr(rec); /* // Min datetime rec.key(DBA_KEY_YEARMIN).seti(sqlrec.out_datetime.year); rec.key(DBA_KEY_MONTHMIN).seti(sqlrec.out_datetime.month); rec.key(DBA_KEY_DAYMIN).seti(sqlrec.out_datetime.day); rec.key(DBA_KEY_HOURMIN).seti(sqlrec.out_datetime.hour); rec.key(DBA_KEY_MINUMIN).seti(sqlrec.out_datetime.minute); rec.key(DBA_KEY_SECMIN).seti(sqlrec.out_datetime.second); // Max datetime rec.key(DBA_KEY_YEARMAX).seti(out_datetime_max.year); rec.key(DBA_KEY_MONTHMAX).seti(out_datetime_max.month); rec.key(DBA_KEY_DAYMAX).seti(out_datetime_max.day); rec.key(DBA_KEY_HOURMAX).seti(out_datetime_max.hour); rec.key(DBA_KEY_MINUMAX).seti(out_datetime_max.minute); rec.key(DBA_KEY_SECMAX).seti(out_datetime_max.second); // Abuse id_data and datetime for count and min(datetime) rec.key(DBA_KEY_LIMIT).seti(sqlrec.out_id_data); */ } unsigned CursorSummary::test_iterate(FILE* dump) { Record r; unsigned count; for (count = 0; next(); ++count) { if (dump) { to_record(r); fprintf(dump, "%02d %03d %03d %s %04d-%02d-%02d %02d:%02d:%02d %04d-%02d-%02d %02d:%02d:%02d %d\n", r.get(DBA_KEY_ANA_ID, -1), r.get(DBA_KEY_REP_COD, -1), (int)sqlrec.out_id_ltr, r.get(DBA_KEY_VAR, ""), r.get(DBA_KEY_YEARMIN, 0), r.get(DBA_KEY_MONTHMIN, 0), r.get(DBA_KEY_DAYMIN, 0), r.get(DBA_KEY_HOURMIN, 0), r.get(DBA_KEY_MINUMIN, 0), r.get(DBA_KEY_SECMIN, 0), r.get(DBA_KEY_YEARMAX, 0), r.get(DBA_KEY_MONTHMAX, 0), r.get(DBA_KEY_DAYMAX, 0), r.get(DBA_KEY_HOURMAX, 0), r.get(DBA_KEY_MINUMAX, 0), r.get(DBA_KEY_SECMAX, 0), r.get(DBA_KEY_LIMIT, -1)); } } return count; } #endif } } } } #include "dballe/memdb/results.tcc" dballe-7.7/dballe/db/mem/cursor.h0000644000175000017500000000321512652630043013611 00000000000000#ifndef DBA_DB_MEM_CURSOR_H #define DBA_DB_MEM_CURSOR_H #include #include #include #include namespace dballe { struct DB; struct Record; namespace memdb { template class ValueStorage; } namespace db { namespace mem { struct DB; /** * Simple typedef to make typing easier, and also to help some versions of swig * match this complex type */ typedef std::vector AttrList; namespace cursor { std::unique_ptr createStations(mem::DB& db, unsigned modifiers, memdb::Results& res); std::unique_ptr createStationData(mem::DB& db, unsigned modifiers, memdb::Results& res); std::unique_ptr createData(mem::DB& db, unsigned modifiers, memdb::Results& res); std::unique_ptr createDataBest(mem::DB& db, unsigned modifiers, memdb::Results& res); std::unique_ptr createSummary(mem::DB& db, unsigned modifiers, memdb::Results& res); /** * Wrapper around a Value index that compares so that all values from which the * best report should be selected appear to be the same. * * This is exported only so that it can be unit tested. */ struct DataBestKey { const memdb::ValueStorage& values; size_t idx; DataBestKey(const memdb::ValueStorage& values, size_t idx); const memdb::Value& value() const { return *values[idx]; } bool operator<(const DataBestKey& o) const; }; std::ostream& operator<<(std::ostream& out, const DataBestKey& k); } } } } #endif dballe-7.7/dballe/db/mem/db.h0000644000175000017500000001050412652630043012660 00000000000000#ifndef DBA_DB_MEM_H #define DBA_DB_MEM_H #include #include #include #include #include #include #include namespace dballe { namespace db { namespace mem { /// DB-ALLe database, in-memory db implementation class DB : public dballe::DB { public: /// In-memory database backend Memdb memdb; Repinfo repinfo; protected: std::string serialization_dir; /// Query stations, returning a list of station IDs void raw_query_stations(const core::Query& rec, memdb::Results& res); /// Query station data, returning a list of Value IDs void raw_query_station_data(const core::Query& rec, memdb::Results& res); /// Query data, returning a list of Value IDs void raw_query_data(const core::Query& rec, memdb::Results& res); public: DB(); DB(const std::string& arg); virtual ~DB(); db::Format format() const override { return MEM; } void disappear() override ; /** * Reset the database, removing all existing DBALLE tables and re-creating them * empty. * * @param repinfo_file * The name of the CSV file with the report type information data to load. * The file is in CSV format with 6 columns: report code, mnemonic id, * description, priority, descriptor, table A category. * If repinfo_file is NULL, then the default of /etc/dballe/repinfo.csv is * used. */ void reset(const char* repinfo_file = 0) override; /** * Update the repinfo table in the database, with the data found in the given * file. * * @param repinfo_file * The name of the CSV file with the report type information data to load. * The file is in CSV format with 6 columns: report code, mnemonic id, * description, priority, descriptor, table A category. * If repinfo_file is NULL, then the default of /etc/dballe/repinfo.csv is * used. * @retval added * The number of repinfo entryes that have been added * @retval deleted * The number of repinfo entryes that have been deleted * @retval updated * The number of repinfo entryes that have been updated */ void update_repinfo(const char* repinfo_file, int* added, int* deleted, int* updated) override; std::map get_repinfo_priorities() override; void insert_station_data(StationValues& vals, bool can_replace, bool station_can_add) override; void insert_data(DataValues& vals, bool can_replace, bool station_can_add) override; void remove_station_data(const Query& query) override; void remove(const Query& rec) override; void remove_all() override; /** * Remove orphan values from the database. * * Orphan values are currently: * \li lev_tr values for which no data exists * \li station values for which no lev_tr exists * * Depending on database size, this routine can take a few minutes to execute. */ void vacuum() override; std::unique_ptr query_stations(const Query& query) override; std::unique_ptr query_station_data(const Query& query) override; std::unique_ptr query_data(const Query& query) override; std::unique_ptr query_summary(const Query& query) override; void attr_query_station(int data_id, std::function)>&& dest) override; void attr_query_data(int data_id, std::function)>&& dest) override; void attr_insert_station(int data_id, const Values& attrs) override; void attr_insert_data(int data_id, const Values& attrs) override; void attr_remove_station(int data_id, const db::AttrList& qcs) override; void attr_remove_data(int data_id, const db::AttrList& qcs) override; bool is_station_variable(int data_id, wreport::Varcode varcode) override; void import_msg(const Message& msg, const char* repmemo, int flags) override; bool export_msgs(const Query& query, std::function&&)> dest) override; /** * Dump the entire contents of the database to an output stream */ void dump(FILE* out) override; friend class dballe::DB; }; } } } #endif dballe-7.7/dballe/db/sql.h0000644000175000017500000000732212652630043012320 00000000000000/* * db/sql - Generic infrastructure for talking with SQL databases * * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_INTERNALS_H #define DBALLE_DB_INTERNALS_H #include #include #include /// Define this to enable referential integrity #undef USE_REF_INT /** Trace macros internally used for debugging * @{ */ // #define TRACE_DB #ifdef TRACE_DB #define TRACE(...) fprintf(stderr, __VA_ARGS__) #define IFTRACE if (1) #else /** Ouput a trace message */ #define TRACE(...) do { } while (0) /** Prefix a block of code to compile only if trace is enabled */ #define IFTRACE if (0) #endif /** @} */ namespace dballe { class Datetime; class Querybuf; namespace db { class Transaction; class Statement; /** * Supported SQL servers. */ enum class ServerType { MYSQL, SQLITE, ORACLE, POSTGRES, }; class Connection { protected: std::string url; public: /** * Type of SQL server we are connected to. * * Use this to tell which SQL dialect to use, in case standard SQL * behaviour is not enough */ ServerType server_type; virtual ~Connection(); const std::string& get_url() const { return url; } /** * Begin a transaction. * * The transaction will be controller by the returned Transaction object, * and will end when its destuctor is called. */ virtual std::unique_ptr transaction() = 0; /// Check if the database contains a table virtual bool has_table(const std::string& name) = 0; /** * Get a value from the settings table. * * Returns the empty string if the table does not exist. */ virtual std::string get_setting(const std::string& key) = 0; /** * Set a value in the settings table. * * The table is created if it does not exist. */ virtual void set_setting(const std::string& key, const std::string& value) = 0; /// Drop the settings table virtual void drop_settings() = 0; /// Format a datetime and add it to the querybuf virtual void add_datetime(Querybuf& qb, const Datetime& dt) const; /// Create a new connection from a URL static std::unique_ptr create_from_url(const char* url); /// Create a new connection from a URL static std::unique_ptr create_from_url(const std::string& url); }; /** * A RAII transaction interface. * * The transaction will be valid during the lifetime of this object. * * You can commit or rollback the transaction using its methods. If at * destruction time the transaction has not been committed or rolled back, a * rollback is automatically performed. */ class Transaction { public: virtual ~Transaction() {} /// Commit this transaction virtual void commit() = 0; /// Roll back this transaction virtual void rollback() = 0; /// Get an exclusive lock on the given table until the end of the /// transaction virtual void lock_table(const char* name) = 0; }; } } #endif dballe-7.7/dballe/db/summary.h0000644000175000017500000001051212652630043013211 00000000000000#ifndef DBALLE_DB_SUMMARY_H #define DBALLE_DB_SUMMARY_H #include #include #include #include namespace dballe { namespace db { class Matcher; class Summary; namespace summary { /// Represent whether a summary can satisfy a given query enum Support { /// It cannot. UNSUPPORTED = 0, /// The query may select less data than this summary can estimate. OVERESTIMATED = 1, /// The query selects data that this summary can estimate exactly. EXACT = 2, }; struct Entry { int ana_id; std::string rep_memo; dballe::Level level; dballe::Trange trange; wreport::Varcode varcode; dballe::DatetimeRange dtrange; int count = MISSING_INT; Entry(db::CursorSummary& cur, bool want_details); }; } /** * High level objects for working with DB-All.e DB summaries */ class Summary { protected: // Query that generated this summary core::Query query; // Summary of items for the currently active filter std::vector summary; void aggregate(const summary::Entry& entry); public: Summary(const dballe::Query& query); // True if the summary has been filled with data bool valid = false; std::set all_stations; std::set all_reports; std::set all_levels; std::set all_tranges; std::set all_varcodes; // Last known datetime range for the data that we have dballe::DatetimeRange dtrange; // Last known count for the data that we have unsigned count = MISSING_INT; /// Return true if the summary has been filled with data bool is_valid() const { return valid; } const Datetime& datetime_min() const { return dtrange.min; } const Datetime& datetime_max() const { return dtrange.max; } unsigned data_count() const { return count; } /** * Checks if this summary correctly generate a * summary for the given query. */ summary::Support supports(const Query& query) const; /// Add an entry to the summary taken from the current status of \a cur void add_summary(db::CursorSummary& cur, bool with_details); /// Add a copy of an existing entry void add_entry(const summary::Entry& entry); /// Iterate all values in the summary bool iterate(std::function f) const; }; namespace summary { /** * Stack of summary in increasing order of selectivity. * * This is used to keep enough context to refine a summary as a query is * refined, and to go back to a wider summary if the query is relaxed. * * Ideally, there could be several levels in the stack, so that each subquery * takes the previous one as a starting point, and the process gets faster and * faster; however, a summary may support a query (in the sense that it knows * that that query selects no data at all) while a more general summary may * support it and return data (e.g. ask first for rep_memo=synop, then change * one's mind and ask for rep_memo=temp. * * Supporting such scenarios would require implementing nontrivial logic for an * optimization that it is still unclear to me if it would be required. At the * moment, I simplify implementation by just supporting two levels, and having * each query always start from the topmost summary. */ class Stack { protected: /** * Summaries for the current query. * * summaries[0] is always the summary for the whole database; * further summaries are appended as the query is refined. */ std::vector summaries; public: /// Check if the stack is empty bool empty() const { return summaries.empty(); } /// Return the stack size. Only really useful for tests. unsigned size() const { return summaries.size(); } /// Add a new summary to the stack, and return a reference to it Summary& push(const Query& query); /// Return the topmost summary const Summary& top() const { return summaries.back(); } /** * If the current summary stack can support the given query, append the * resulting summary to the stack, else, remove all entries from the stack * except the most general one. * * @returns how the resulting stack supports the query. */ Support query(const Query& query, bool exact, std::function match); }; } } } #endif dballe-7.7/dballe/db/db-query-station-test.cc0000644000175000017500000002446712652630043016054 00000000000000#include "config.h" #include "db/tests.h" #include "db/mem/db.h" #include "db/v6/db.h" #include "db/sql/station.h" using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct DBData : public TestDataSet { DBData() { stations["st1_synop"].info.coords = Coords(12.34560, 76.54320); stations["st1_synop"].info.report = "synop"; stations["st1_synop"].values.set(newvar("block", 1)); stations["st1_synop"].values.set(newvar("station", 1)); stations["st1_synop"].values.set(newvar("B07030", 42.0)); // height stations["st1_metar"].info = stations["st1_synop"].info; stations["st1_metar"].info.report = "metar"; stations["st1_metar"].values.set(newvar("block", 1)); stations["st1_metar"].values.set(newvar("station", 2)); stations["st1_metar"].values.set(newvar("B07030", 50.0)); // height stations["st2_temp"].info.coords = Coords(23.45670, 65.43210); stations["st2_temp"].info.report = "temp"; stations["st2_temp"].values.set(newvar("block", 3)); stations["st2_temp"].values.set(newvar("station", 4)); stations["st2_temp"].values.set(newvar("B07030", 100.0)); // height stations["st2_metar"].info = stations["st2_temp"].info; stations["st2_metar"].info.report = "metar"; stations["st2_metar"].values.set(newvar("block", 3)); stations["st2_metar"].values.set(newvar("station", 4)); stations["st2_metar"].values.set(newvar("B07030", 110.0)); // height data["rec1"].info = stations["st1_metar"].info; data["rec1"].info.datetime = Datetime(1945, 4, 25, 8); data["rec1"].info.level = Level(10, 11, 15, 22); data["rec1"].info.trange = Trange(20, 111, 122); data["rec1"].values.set("B12101", 290.0); data["rec2"].info = stations["st2_metar"].info; data["rec2"].info.datetime = Datetime(1945, 4, 25, 8); data["rec2"].info.level = Level(10, 11, 15, 22); data["rec2"].info.trange = Trange(20, 111, 122); data["rec2"].values.set("B12101", 300.0); data["rec2"].values.set("B12103", 298.0); } }; struct Fixture : public DBFixture { const int some; const int all; Fixture(const char* backend, db::Format format) : DBFixture(backend, format), some(format == MEM ? 2 : 1), all(format == MEM ? 4 : 2) #warning FIXME: change after testing if we can move to report-in-station behaviour or not { } void test_setup() { DBFixture::test_setup(); wassert(populate()); } }; #define TRY_QUERY(qstring, expected_count) wassert(actual(*f.db).try_data_query(qstring, expected_count)) class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("query_ana_id", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_station_query("ana_id=1", 1)); wassert(actual(db).try_station_query("ana_id=2", 1)); }); add_method("query_lat_lon", [](Fixture& f) { auto& db = *f.db; const auto some = f.some; const auto all = f.all; wassert(actual(db).try_station_query("lat=12.00000", 0)); wassert(actual(db).try_station_query("lat=12.34560", some)); wassert(actual(db).try_station_query("lat=23.45670", some)); wassert(actual(db).try_station_query("latmin=12.00000", all)); wassert(actual(db).try_station_query("latmin=12.34560", all)); wassert(actual(db).try_station_query("latmin=12.34570", some)); wassert(actual(db).try_station_query("latmin=23.45670", some)); wassert(actual(db).try_station_query("latmin=23.45680", 0)); wassert(actual(db).try_station_query("latmax=12.00000", 0)); wassert(actual(db).try_station_query("latmax=12.34560", some)); wassert(actual(db).try_station_query("latmax=12.34570", some)); wassert(actual(db).try_station_query("latmax=23.45670", all)); wassert(actual(db).try_station_query("latmax=23.45680", all)); wassert(actual(db).try_station_query("lon=76.00000", 0)); wassert(actual(db).try_station_query("lon=76.54320", some)); wassert(actual(db).try_station_query("lon=65.43210", some)); wassert(actual(db).try_station_query("lonmin=10., lonmax=20.", 0)); wassert(actual(db).try_station_query("lonmin=76.54320, lonmax=76.54320", some)); wassert(actual(db).try_station_query("lonmin=76.54320, lonmax=77.", some)); wassert(actual(db).try_station_query("lonmin=76.54330, lonmax=77.", 0)); wassert(actual(db).try_station_query("lonmin=60., lonmax=77.", all)); wassert(actual(db).try_station_query("lonmin=77., lonmax=76.54310", some)); wassert(actual(db).try_station_query("lonmin=77., lonmax=76.54320", all)); wassert(actual(db).try_station_query("lonmin=77., lonmax=-10", 0)); }); add_method("query_mobile", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_station_query("mobile=0", f.all)); wassert(actual(db).try_station_query("mobile=1", 0)); }); add_method("query_ident", [](Fixture& f) { // FIXME: add some mobile stations to the test fixture to test ident }); add_method("query_block_station", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_station_query("B01001=1", f.some)); wassert(actual(db).try_station_query("B01001=2", 0)); wassert(actual(db).try_station_query("B01001=3", f.some)); wassert(actual(db).try_station_query("B01001=4", 0)); wassert(actual(db).try_station_query("B01002=1", 1)); wassert(actual(db).try_station_query("B01002=2", 1)); wassert(actual(db).try_station_query("B01002=3", 0)); wassert(actual(db).try_station_query("B01002=4", f.some)); }); add_method("query_mobile", [](Fixture& f) { auto& db = *f.db; }); add_method("query_ana_filter", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_station_query("ana_filter=block=1", f.some)); wassert(actual(db).try_station_query("ana_filter=block=2", 0)); wassert(actual(db).try_station_query("ana_filter=block=3", f.some)); wassert(actual(db).try_station_query("ana_filter=block>=1", f.all)); wassert(actual(db).try_station_query("ana_filter=B07030=42", 1)); wassert(actual(db).try_station_query("ana_filter=B07030=50", 1)); wassert(actual(db).try_station_query("ana_filter=B07030=100", 1)); wassert(actual(db).try_station_query("ana_filter=B07030=110", 1)); wassert(actual(db).try_station_query("ana_filter=B07030=120", 0)); wassert(actual(db).try_station_query("ana_filter=B07030>50", f.some)); #warning FIXME: change after testing if we can move to report-in-station behaviour or not if (db.format() == MEM) wassert(actual(db).try_station_query("ana_filter=B07030>=50", 3)); else wassert(actual(db).try_station_query("ana_filter=B07030>=50", 2)); wassert(actual(db).try_station_query("ana_filter=50<=B07030<=100", 2)); }); add_method("query_var", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_station_query("var=B12101", 2)); wassert(actual(db).try_station_query("var=B12103", 1)); wassert(actual(db).try_station_query("varlist=B12101", 2)); wassert(actual(db).try_station_query("varlist=B12103", 1)); #warning FIXME: change after testing if we can move to report-in-station behaviour or not if (db.format() == MEM) wassert(actual(db).try_station_query("varlist=B12101,B12103", 3)); else wassert(actual(db).try_station_query("varlist=B12101,B12103", 2)); }); add_method("stations_without_data", [](Fixture& f) { auto& db = *f.db; // Manually insert an orphan station switch (db.format()) { case MEM: if (auto d = dynamic_cast(f.db)) d->memdb.stations.obtain_fixed(Coords(11.0, 45.0), "synop"); break; case V6: if (auto d = dynamic_cast(f.db)) d->station().obtain_id(1100000, 4500000); break; case V5: throw error_unimplemented("v5 db is not supported"); case MESSAGES: throw error_unimplemented("testing stations_without_data on MESSAGES database"); } // Query stations and make sure that they do not appear. They should // not appear, but they currently do because of a bug. I need to // preserve the bug until the software that relies on it has been // migrated to use standard DB-All.e features. core::Query query; query.latrange.set(11.0, 11.0); query.lonrange.set(45.0, 45.0); auto cur = db.query_stations(query); #warning TODO: fix this test to give an error once we do not need to support this bug anymore //wassert(actual(cur->remaining()) == 0); wassert(actual(cur->remaining()) == 1); }); add_method("query_ordering", [](Fixture& f) { auto& db = *f.db; auto cur = db.query_stations(core::Query()); switch (db.format()) { case MEM: wassert(actual(cur->remaining()) == 4); break; case V6: wassert(actual(cur->remaining()) == 2); break; default: error_unimplemented::throwf("cannot run this test on a database of format %d", (int)db.format()); } }); } }; Tests tg1("db_query_station_mem", nullptr, db::MEM); Tests tg2("db_query_station_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg4("db_query_station_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg6("db_query_station_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg8("db_query_station_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/db-misc-test.cc0000644000175000017500000011244412652630043014154 00000000000000#include "config.h" #include "db/tests.h" #include "db/querybuf.h" #include "db/mem/db.h" #include using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct NavileDataSet : public TestDataSet { NavileDataSet() { stations["synop"].info.coords = Coords(44.5008, 11.3288); stations["synop"].info.report = "synop"; stations["synop"].values.set("B07030", 78); // Height } }; unsigned run_attr_query_station(DB& db, int data_id, Values& dest) { unsigned count = 0; db.attr_query_station(data_id, [&](unique_ptr var) { dest.set(move(var)); ++count; }); return count; } unsigned run_attr_query_data(DB& db, int data_id, Values& dest) { unsigned count = 0; db.attr_query_data(data_id, [&](unique_ptr var) { dest.set(move(var)); ++count; }); return count; } class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("insert", [](Fixture& f) { // Test a simple insert round trip auto& db = *f.db; // Insert some data NavileDataSet ds; ds.data["synop"].info = ds.stations["synop"].info; ds.data["synop"].info.datetime = Datetime(2013, 10, 16, 10); ds.data["synop"].values.set(WR_VAR(0, 12, 101), 16.5); wassert(f.populate_database(ds)); Values attrs; attrs.set("B33007", 50); wassert(db.attr_insert_data(ds.data["synop"].values[WR_VAR(0, 12, 101)].data_id, attrs)); // Query and verify the station data { auto cur = db.query_stations(core::Query()); wassert(actual(cur->remaining()) == 1); cur->next(); wassert(actual(cur).station_vars_match(ds.stations["synop"])); } // Query and verify the measured data { auto cur = db.query_data(core::Query()); wassert(actual(cur->remaining()) == 1); cur->next(); wassert(actual(cur).data_context_matches(ds.data["synop"])); wassert(actual(cur).data_var_matches(ds.data["synop"], WR_VAR(0, 12, 101))); } // Query and verify attributes { int count = 0; unique_ptr attr; wassert(db.attr_query_data(ds.data["synop"].values[WR_VAR(0, 12, 101)].data_id, [&](std::unique_ptr&& var) { ++count; attr = move(var); })); wassert(actual(count) == 1); wassert(actual(attr->code()) == WR_VAR(0, 33, 7)); wassert(actual(attr->enq(MISSING_INT)) == 50); } }); add_method("insert_perms", [](Fixture& f) { // Test insert auto& db = *f.db; OldDballeTestDataSet oldf; // Check if adding a nonexisting station when not allowed causes an error try { db.insert_data(oldf.data["synop"], false, false); throw TestFailed("error_consistency should have been thrown"); } catch (error_consistency& e) { wassert(actual(e.what()).contains("insert a station entry when it is forbidden")); } catch (error_notfound& e) { wassert(actual(e.what()).contains("station not found")); } wassert(actual(oldf.data["synop"].info.ana_id) == MISSING_INT); wassert(actual(oldf.data["synop"].values["B01011"].data_id) == MISSING_INT); wassert(actual(oldf.data["synop"].values["B01012"].data_id) == MISSING_INT); oldf.data["synop"].clear_ids(); // Insert the record wassert(db.insert_data(oldf.data["synop"], false, true)); oldf.data["synop"].clear_ids(); // Check if duplicate updates are allowed by insert wassert(db.insert_data(oldf.data["synop"], true, false)); oldf.data["synop"].clear_ids(); // Check if overwrites are trapped by insert_new oldf.data["synop"].values.set("B01011", "DB-All.e?"); try { db.insert_data(oldf.data["synop"], false, false); throw TestFailed("wreport::error should have been thrown"); } catch (wreport::error& e) { wassert(actual(e.what()).matches("refusing to overwrite existing data|cannot replace an existing value|Duplicate entry")); } }); add_method("insert_twice", [](Fixture& f) { // Test double station insert auto& db = *f.db; OldDballeTestDataSet oldf; // Insert the record twice wassert(db.insert_data(oldf.data["synop"], false, true)); // This should fail, refusing to replace station info oldf.data["synop"].values.set("B01011", "DB-All.e?"); try { db.insert_data(oldf.data["synop"], false, true); throw TestFailed("wreport::error should have been thrown"); } catch (wreport::error& e) { wassert(actual(e.what()).matches("refusing to overwrite existing data|cannot replace an existing value|Duplicate entry")); } }); add_method("query_station", [](Fixture& f) { // Test station query auto& db = *f.db; OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); // Iterate the station database auto cur = db.query_stations(core::Query()); if (dynamic_cast(f.db)) { // Memdb has one station entry per (lat, lon, ident, network) wassert(actual(cur->remaining()) == 2); wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_lat()) == 12.34560); wassert(actual(cur->get_lon()) == 76.54320); wassert(actual(cur->get_rep_memo()) == "synop"); wassert(actual((void*)cur->get_ident()) == (void*)0); wassert(actual(cur).station_keys_match(oldf.stations["synop"].info)); wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_lat()) == 12.34560); wassert(actual(cur->get_lon()) == 76.54320); wassert(actual(cur->get_rep_memo()) == "metar"); wassert(actual((void*)cur->get_ident()) == (void*)0); wassert(actual(cur).station_keys_match(oldf.stations["metar"].info)); } else { // V5 and V6 have one station entry (lat, lon, ident) wassert(actual(cur->remaining()) == 1); // There should be an item wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_lat()) == 12.34560); wassert(actual(cur->get_lon()) == 76.54320); wassert(actual((void*)cur->get_ident()) == (void*)0); // Check that the result matches wassert(actual(cur).station_keys_match(oldf.stations["metar"].info)); // There should be only one item } wassert(actual(cur->remaining()) == 0); wassert(actual(cur->next()).isfalse()); }); add_method("query_best", [](Fixture& f) { // Test querybest auto& db = *f.db; OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); //if (db.server_type == ORACLE || db.server_type == POSTGRES) // return; // Prepare a query core::Query query; query.latrange = LatRange(1000000, LatRange::IMAX); query.query = "best"; // Make the query auto cur = db.query_data(query); wassert(actual(cur->remaining()) == 4); // There should be four items wassert(actual(cur->next()).istrue()); wassert(actual(cur->get_lat()) == 12.34560); wassert(actual(cur->get_lon()) == 76.54320); wassert(actual((void*)cur->get_ident()) == (void*)0); wassert(actual((void*)cur->get_rep_memo()).istrue()); wassert(actual(cur->get_rep_memo()) == "synop"); wassert(actual(cur->get_level()) == Level(10, 11, 15, 22)); wassert(actual(cur->get_trange()) == Trange(20, 111, 122)); wassert(actual(cur->get_varcode()) == WR_VAR(0, 1, 11)); wassert(actual(cur->get_var().code()) == WR_VAR(0, 1, 11)); wassert(actual(cur->remaining()) == 3); wassert(actual(cur->next()).istrue()); wassert(actual(cur->remaining()) == 2); wassert(actual(cur->next()).istrue()); wassert(actual(cur->remaining()) == 1); wassert(actual(cur->next()).istrue()); wassert(actual(cur->remaining()) == 0); // Now there should not be anything anymore wassert(actual(cur->next()).isfalse()); }); add_method("delete", [](Fixture& f) { // Test deletion auto& db = *f.db; OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); // 4 items to begin with core::Query query; auto cur = db.query_data(query); wassert(actual(cur->remaining()) == 4); cur->discard_rest(); query.clear(); query.datetime = DatetimeRange(Datetime(1945, 4, 25, 8, 10), Datetime()); db.remove(query); // 2 remaining after remove query.clear(); cur = db.query_data(query); wassert(actual(cur->remaining()) == 2); cur->discard_rest(); // Did it remove the right ones? query.clear(); query.latrange = LatRange(10.0, LatRange::DMAX); cur = db.query_data(query); wassert(actual(cur->remaining()) == 2); wassert(actual(cur->next()).istrue()); wassert(actual(cur).data_context_matches(oldf.data["synop"])); Varcode last_code = 0; for (unsigned i = 0; i < 2; ++i) { // Check that varcodes do not repeat if (last_code != 0) wassert(actual(cur->get_varcode()) != last_code); last_code = cur->get_varcode(); switch (last_code) { case WR_VAR(0, 1, 11): case WR_VAR(0, 1, 12): wassert(actual(cur).data_var_matches(oldf.data["synop"], last_code)); break; default: throw TestFailed("got a varcode that we did not ask for: " + varcode_format(last_code)); } if (i == 0) { /* The item should have two data in it */ wassert(actual(cur->next()).istrue()); } else { wassert(actual(cur->next()).isfalse()); } } }); add_method("delete_notfound", [](Fixture& f) { // Test deletion auto& db = *f.db; OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); // 4 items to begin with core::Query query; auto cur = db.query_data(query); wassert(actual(cur->remaining()) == 4); cur->discard_rest(); // Try to remove using a query that matches none query.attr_filter = "B33007<50"; db.remove(query); // Verify that nothing has been deleted query.clear(); cur = db.query_data(query); wassert(actual(cur->remaining()) == 4); cur->discard_rest(); }); add_method("query_datetime", [](Fixture& f) { // Test datetime queries auto& db = *f.db; /* Prepare test data */ DataValues base; base.info.coords = Coords(12.0, 48.0); base.info.report = "synop"; base.info.level = Level(1, 0, 1, 0); base.info.trange = Trange(1, 0, 0); base.values.set("B01012", 500); #define WANTRESULT(querystr, ab) do { \ core::Record result; \ auto cur = db.query_data(*dballe::tests::query_from_string(querystr)); \ wassert(actual(cur->remaining()) == 1); \ wassert(actual(cur->next()).istrue()); \ cur->to_record(result); \ wassert(actual(cur->remaining()) == 0); \ wassert(actual_varcode(result.vars()[0]->code()) == WR_VAR(0, 1, 12)); \ wassert(actual(cur->get_datetime()) == ab.info.datetime); \ cur->discard_rest(); \ } while(0) DataValues a, b; /* Year */ db.reset(); a = base; a.info.datetime = Datetime(2005); db.insert_data(a, false, true); b = base; b.info.datetime = Datetime(2006); db.insert_data(b, false, false); WANTRESULT("yearmin=2006", b); WANTRESULT("yearmax=2005", a); WANTRESULT("year=2006", b); /* Month */ db.reset(); a = base; a.info.datetime = Datetime(2006, 4); db.insert_data(a, false, true); b = base; b.info.datetime = Datetime(2006, 5); db.insert_data(b, false, false); WANTRESULT("year=2006, monthmin=5", b); WANTRESULT("year=2006, monthmax=4", a); WANTRESULT("year=2006, month=5", b); /* Day */ db.reset(); a = base; a.info.datetime = Datetime(2006, 5, 2); db.insert_data(a, false, true); b = base; b.info.datetime = Datetime(2006, 5, 3); db.insert_data(b, false, false); WANTRESULT("year=2006, month=5, daymin=3", b); WANTRESULT("year=2006, month=5, daymax=2", a); WANTRESULT("year=2006, month=5, day=3", b); /* Hour */ db.reset(); a = base; a.info.datetime = Datetime(2006, 5, 3, 12); db.insert_data(a, false, true); b = base; b.info.datetime = Datetime(2006, 5, 3, 13); db.insert_data(b, false, false); WANTRESULT("year=2006, month=5, day=3, hourmin=13", b); WANTRESULT("year=2006, month=5, day=3, hourmax=12", a); WANTRESULT("year=2006, month=5, day=3, hour=13", b); /* Minute */ db.reset(); a = base; a.info.datetime = Datetime(2006, 5, 3, 12, 29); db.insert_data(a, false, true); b = base; b.info.datetime = Datetime(2006, 5, 3, 12, 30); db.insert_data(b, false, false); WANTRESULT("year=2006, month=5, day=3, hour=12, minumin=30", b); WANTRESULT("year=2006, month=5, day=3, hour=12, minumax=29", a); WANTRESULT("year=2006, month=5, day=3, hour=12, min=30", b); }); add_method("attrs", [](Fixture& f) { // Test QC auto& db = *f.db; OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); core::Query query; core::Record result; query.latrange.set(1000000, LatRange::IMAX); auto cur = db.query_data(query); // Move the cursor to B01011 int context_id; bool found = false; while (cur->next()) { cur->to_record(result); if (result.vars()[0]->code() == WR_VAR(0, 1, 11)) { context_id = cur->attr_reference_id(); cur->discard_rest(); found = true; break; } } wassert(actual(found).istrue()); // Insert new attributes about this report Values qc; qc.set("B33002", 2); qc.set("B33003", 5); qc.set("B33005", 33); db.attr_insert_data(context_id, qc); // Query back the data qc.clear(); wassert(actual(run_attr_query_data(db, context_id, qc)) == 3); const auto* attr = qc.get("B33002"); wassert(actual(attr).istrue()); wassert(actual(attr->var->enqi()) == 2); attr = qc.get("B33003"); wassert(actual(attr).istrue()); wassert(actual(attr->var->enqi()) == 5); attr = qc.get("B33005"); wassert(actual(attr).istrue()); wassert(actual(attr->var->enqi()) == 33); // Delete a couple of items vector codes; codes.push_back(WR_VAR(0, 33, 2)); codes.push_back(WR_VAR(0, 33, 5)); db.attr_remove_data(context_id, codes); // Deleting non-existing items should not fail. Also try creating a // query with just one item codes.clear(); codes.push_back(WR_VAR(0, 33, 2)); db.attr_remove_data(context_id, codes); /* Query back the data */ qc.clear(); wassert(actual(run_attr_query_data(db, context_id, qc)) == 1); wassert(actual(qc.get("B33002")).isfalse()); wassert(actual(qc.get("B33005")).isfalse()); attr = qc.get("B33003"); wassert(actual(attr).istrue()); wassert(actual(attr->var->enqi()) == 5); /*dba_error_remove_callback(DBA_ERR_NONE, crash, 0);*/ }); add_method("query_station", [](Fixture& f) { // Test station queries auto& db = *f.db; OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); auto cur = db.query_stations(*query_from_string("rep_memo=synop")); wassert(actual(cur->remaining()) == 1); wassert(actual(cur->next()).istrue()); wassert(actual(cur->next()).isfalse()); }); add_method("attrs1", [](Fixture& f) { // Test attributes auto& db = *f.db; OldDballeTestDataSet oldf; // Insert a data record db.insert_data(oldf.data["synop"], true, true); Values qc; qc.set("B01007", 1); qc.set("B02048", 2); qc.set("B05040", 3); qc.set("B05041", 4); qc.set("B05043", 5); qc.set("B33032", 6); qc.set("B07024", 7); qc.set("B05021", 8); qc.set("B07025", 9); qc.set("B05022", 10); db.attr_insert_data(oldf.data["synop"].values[WR_VAR(0, 1, 11)].data_id, qc); // Query back the B01011 variable to read the attr reference id auto cur = db.query_data(*query_from_string("var=B01011")); wassert(actual(cur->remaining()) == 1); cur->next(); int attr_id = cur->attr_reference_id(); cur->discard_rest(); qc.clear(); wassert(actual(run_attr_query_data(db, attr_id, qc)) == 10); // Check that all the attributes come out wassert(actual(qc.size()) == 10); wassert(actual_varcode(qc["B01007"].var->code()) == WR_VAR(0, 1, 7)); wassert(actual(*qc["B01007"].var) == 1); wassert(actual_varcode(qc["B02048"].var->code()) == WR_VAR(0, 2, 48)); wassert(actual(*qc["B02048"].var) == 2); wassert(actual_varcode(qc["B05021"].var->code()) == WR_VAR(0, 5, 21)); wassert(actual(*qc["B05021"].var) == 8); wassert(actual_varcode(qc["B05022"].var->code()) == WR_VAR(0, 5, 22)); wassert(actual(*qc["B05022"].var) == 10); wassert(actual_varcode(qc["B05040"].var->code()) == WR_VAR(0, 5, 40)); wassert(actual(*qc["B05040"].var) == 3); wassert(actual_varcode(qc["B05041"].var->code()) == WR_VAR(0, 5, 41)); wassert(actual(*qc["B05041"].var) == 4); wassert(actual_varcode(qc["B05043"].var->code()) == WR_VAR(0, 5, 43)); wassert(actual(*qc["B05043"].var) == 5); wassert(actual_varcode(qc["B07024"].var->code()) == WR_VAR(0, 7, 24)); wassert(actual(*qc["B07024"].var) == 7); wassert(actual_varcode(qc["B07025"].var->code()) == WR_VAR(0, 7, 25)); wassert(actual(*qc["B07025"].var) == 9); wassert(actual_varcode(qc["B33032"].var->code()) == WR_VAR(0, 33, 32)); wassert(actual(*qc["B33032"].var) == 6); }); add_method("longitude_wrap", [](Fixture& f) { // Test longitude wrapping around auto& db = *f.db; OldDballeTestDataSet oldf; // Insert a data record db.insert_data(oldf.data["synop"], true, true); auto cur = db.query_data(*query_from_string("latmin=10.0, latmax=15.0, lonmin=70.0, lonmax=-160.0")); wassert(actual(cur->remaining()) == 2); cur->discard_rest(); }); add_method("query_ana_filter", [](Fixture& f) { // Test numeric comparisons in ana_filter auto& db = *f.db; OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); auto cur = db.query_data(*query_from_string("rep_memo=metar, var=B01011")); wassert(actual(cur->remaining()) == 1); // Move the cursor to B01011 cur->next(); int context_id = cur->attr_reference_id(); cur->discard_rest(); // Insert new attributes about this report Values qc; qc.set("B01001", 50); qc.set("B01008", "50"); db.attr_insert_data(context_id, qc); // Try queries filtered by numeric attributes cur = db.query_data(*query_from_string("rep_memo=metar, var=B01011, attr_filter=B01001=50")); wassert(actual(cur->remaining()) == 1); cur->discard_rest(); cur = db.query_data(*query_from_string("rep_memo=metar, var=B01011, attr_filter=B01001<=50")); wassert(actual(cur->remaining()) == 1); cur->discard_rest(); cur = db.query_data(*query_from_string("rep_memo=metar, var=B01011, attr_filter=B01001<51")); wassert(actual(cur->remaining()) == 1); cur->discard_rest(); cur = db.query_data(*query_from_string("rep_memo=metar, var=B01011, attr_filter=B01001<8")); wassert(actual(cur->remaining()) == 0); cur->discard_rest(); // Try queries filtered by string attributes cur = db.query_data(*query_from_string("rep_memo=metar, var=B01011, attr_filter=B01008=50")); wassert(actual(cur->remaining()) == 1); cur->discard_rest(); cur = db.query_data(*query_from_string("rep_memo=metar, var=B01011, attr_filter=B01008<=50")); wassert(actual(cur->remaining()) == 1); cur->discard_rest(); cur = db.query_data(*query_from_string("rep_memo=metar, var=B01011, attr_filter=B01008<8")); wassert(actual(cur->remaining()) == 1); cur->discard_rest(); cur = db.query_data(*query_from_string("rep_memo=metar, var=B01011, attr_filter=B01008<100")); wassert(actual(cur->remaining()) == 0); cur->discard_rest(); }); add_method("query_station_best", [](Fixture& f) { #warning BEST queries of station values are not yet implemented for memdb if (dynamic_cast(f.db)) return; auto& db = *f.db; // Reproduce a querybest scenario which produced invalid SQL OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); core::Query q; q.datetime = DatetimeRange(Datetime(1000, 1, 1, 0, 0, 0), Datetime(1000, 1, 1, 0, 0, 0)); q.query = "best"; auto cur = db.query_data(q); while (cur->next()) { } }); add_method("query_best_bug1", [](Fixture& f) { auto& db = *f.db; // Reproduce a querybest scenario which produced always the same data record // Import lots const char** files = dballe::tests::bufr_files; for (int i = 0; files[i] != NULL; i++) { Messages inmsgs = read_msgs(files[i], File::BUFR); wassert(db.import_msg(inmsgs[0], NULL, DBA_IMPORT_ATTRS | DBA_IMPORT_FULL_PSEUDOANA | DBA_IMPORT_OVERWRITE)); } // Query all with best auto cur = db.query_data(*query_from_string("var=B12101, query=best")); unsigned orig_count = cur->remaining(); unsigned count = 0; int id_data = 0; unsigned id_data_changes = 0; while (cur->next()) { ++count; if (cur->attr_reference_id() != id_data) { id_data = cur->attr_reference_id(); ++id_data_changes; } } wassert(actual(count) > 1); wassert(actual(id_data_changes) == count); wassert(actual(count) == orig_count); }); add_method("query_invalid_sql", [](Fixture& f) { auto& db = *f.db; // Reproduce a query that generated invalid SQL on V6 OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); // All DB db.query_stations(*query_from_string("leveltype1=103, l1=2000")); }); add_method("fd_leaks", [](Fixture& f) { // Test connect leaks StationValues vals; // Set station data vals.info.coords = Coords(12.34560, 76.54320); vals.info.report = "synop"; vals.values.set("B07030", 42.0); // Height // Assume a max open file limit of 1100 for (unsigned i = 0; i < 1100; ++i) { std::unique_ptr db = f.create_db(); vals.clear_ids(); wassert(db->insert_station_data(vals, true, true)); } }); add_method("update", [](Fixture& f) { auto& db = *f.db; // Test value update OldDballeTestDataSet oldf; DataValues dataset = oldf.data["synop"]; db.insert_data(dataset, true, true); Values attrs; attrs.set("B33007", 50); db.attr_insert_data(dataset.values["B01012"].data_id, attrs); core::Query q; q.latrange.set(12.34560, 12.34560); q.lonrange.set(76.54320, 76.54320); q.datetime = DatetimeRange(Datetime(1945, 4, 25, 8, 0, 0), Datetime(1945, 4, 25, 8, 0, 0)); q.rep_memo = "synop"; q.level = Level(10, 11, 15, 22); q.trange = Trange(20, 111, 122); q.varcodes.insert(WR_VAR(0, 1, 12)); // Query the initial value auto cur = db.query_data(q); wassert(actual(cur->remaining()) == 1); cur->next(); int ana_id = cur->get_station_id(); wreport::Var var = cur->get_var(); wassert(actual(var.enqi()) == 300); // Query the attributes and check that they are there Values qattrs; wassert(actual(run_attr_query_data(db, cur->attr_reference_id(), qattrs)) == 1); wassert(actual(qattrs["B33007"].var->enq(MISSING_INT)) == 50); // Update it DataValues update; update.info.ana_id = ana_id; update.info.report = "synop"; update.info.datetime = q.datetime.min; update.info.level = q.level; update.info.trange = q.trange; update.values.set(var.code(), 200); db.insert_data(update, true, false); // Query again cur = db.query_data(q); wassert(actual(cur->remaining()) == 1); cur->next(); var = cur->get_var(); wassert(actual(var.enqi()) == 200); qattrs.clear(); wassert(actual(run_attr_query_data(db, cur->attr_reference_id(), qattrs)) == 1); wassert(actual(qattrs["B33007"].var->enq(MISSING_INT)) == 50); }); add_method("query_stepbystep", [](Fixture& f) { auto& db = *f.db; // Try a query checking all the steps OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); // Make the query auto cur = db.query_data(*query_from_string("latmin=10.0")); wassert(actual(cur->remaining()) == 4); wassert(actual(cur->next()).istrue()); // remaining() should decrement wassert(actual(cur->remaining()) == 3); // results should match what was inserted wassert(actual(cur).data_matches(oldf.data["synop"])); // just call to_record now, to check if in the next call old variables are removed core::Record result; cur->to_record(result); wassert(actual(cur->next()).istrue()); wassert(actual(cur->remaining()) == 2); wassert(actual(cur).data_matches(oldf.data["synop"])); // Variables from the previous to_record should be removed cur->to_record(result); wassert(actual(result.vars().size()) == 1u); wassert(actual(cur->next()).istrue()); wassert(actual(cur->remaining()) == 1); wassert(actual(cur).data_matches(oldf.data["metar"])); wassert(actual(cur->next()).istrue()); wassert(actual(cur->remaining()) == 0); wassert(actual(cur).data_matches(oldf.data["metar"])); // Now there should not be anything anymore wassert(actual(cur->remaining()) == 0); wassert(actual(cur->next()).isfalse()); }); add_method("insert_stationinfo_twice", [](Fixture& f) { // Test double insert of station info auto& db = *f.db; NavileDataSet ds; //wassert(actual(f.db).empty()); db.insert_station_data(ds.stations["synop"], true, true); db.insert_station_data(ds.stations["synop"], true, true); // Query station data and ensure there is only one info (height) core::Query query; auto cur = db.query_station_data(query); wassert(actual(cur->remaining()) == 1); cur->next(); wassert(actual(cur).station_vars_match(ds.stations["synop"])); }); add_method("insert_stationinfo_twice1", [](Fixture& f) { // Test double insert of station info auto& db = *f.db; NavileDataSet ds; ds.stations["metar"] = ds.stations["synop"]; ds.stations["metar"].info.report = "metar"; db.insert_station_data(ds.stations["synop"], true, true); db.insert_station_data(ds.stations["metar"], true, true); // Query station data and ensure there is only one info (height) core::Query query; auto cur = db.query_station_data(query); wassert(actual(cur->remaining()) == 2); // Ensure that the network info is preserved // Use a sorted vector because while all DBs group by report, not all DBs // sort by report name. vector reports; while (cur->next()) reports.push_back(cur->get_rep_memo()); std::sort(reports.begin(), reports.end()); wassert(actual(reports[0]) == "metar"); wassert(actual(reports[1]) == "synop"); }); add_method("insert_undefined_level2", [](Fixture& f) { // Test handling of values with undefined leveltype2 and l2 auto& db = *f.db; OldDballeTestDataSet oldf; // Insert with undef leveltype2 and l2 DataValues dataset; dataset.info = oldf.data["synop"].info; dataset.info.level = Level(44, 55); dataset.info.trange = Trange(20); dataset.values.set("B01012", 300); db.insert_data(dataset, true, true); // Query it back auto cur = db.query_data(*query_from_string("leveltype1=44, l1=55")); wassert(actual(cur->remaining()) == 1); wassert(actual(cur->next()).istrue()); core::Record result; cur->to_record(result); wassert(actual(result.get_level()) == Level(44, 55)); wassert(actual(result.get_trange()) == Trange(20)); wassert(actual(cur->next()).isfalse()); }); add_method("query_undefined_level2", [](Fixture& f) { // Test handling of values with undefined leveltype2 and l2 auto& db = *f.db; OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); // Query with undef leveltype2 and l2 auto cur = db.query_data(*query_from_string("leveltype1=10, l1=11")); wassert(actual(cur->remaining()) == 4); cur->discard_rest(); }); add_method("query_bad_attrfilter", [](Fixture& f) { // Query with an incorrect attr_filter auto& db = *f.db; OldDballeTestDataSet oldf; wassert(f.populate_database(oldf)); try { db.query_data(*query_from_string("attr_filter=B12001")); } catch (error_consistency& e) { wassert(actual(e.what()).matches("B12001 is not a valid filter|cannot find any operator in filter 'B12001'")); } }); add_method("query_best_priomax", [](Fixture& f) { // Test querying priomax together with query=best auto& db = *f.db; // Prepare the common parts of some data DataValues insert; insert.info.coords = Coords(1.0, 1.0); insert.info.level = Level(1, 0); insert.info.trange = Trange(254, 0, 0); insert.info.datetime = Datetime(2009, 11, 11, 0, 0, 0); // 1,synop,synop,101,oss,0 // 2,metar,metar,81,oss,0 // 3,temp,sounding,98,oss,2 // 4,pilot,wind profile,80,oss,2 // 9,buoy,buoy,50,oss,31 // 10,ship,synop ship,99,oss,1 // 11,tempship,temp ship,100,oss,2 // 12,airep,airep,82,oss,4 // 13,amdar,amdar,97,oss,4 // 14,acars,acars,96,oss,4 // 42,pollution,pollution,199,oss,8 // 200,satellite,NOAA satellites,41,oss,255 // 255,generic,generic data,1000,?,255 static const char* rep_memos[] = { "synop", "metar", "temp", "pilot", "buoy", "ship", "tempship", "airep", "amdar", "acars", "pollution", "satellite", "generic", NULL }; for (const char** i = rep_memos; *i; ++i) { insert.clear_ids(); insert.info.report = *i; insert.values.set("B12101", (int)(i - rep_memos)); db.insert_data(insert, false, true); } // Query with querybest only { core::Query query; query.query = "best"; query.datetime = DatetimeRange(Datetime(2009, 11, 11, 0, 0, 0), Datetime(2009, 11, 11, 0, 0, 0)); query.varcodes.insert(WR_VAR(0, 12, 101)); auto cur = db.query_data(query); wassert(actual(cur->remaining()) == 1); wassert(actual(cur->next()).istrue()); core::Record result; cur->to_record(result); wassert(actual(result.get("rep_memo")).istrue()); wassert(actual(result.enq("rep_memo", "")) == "generic"); cur->discard_rest(); } // Query with querybest and priomax { core::Query query; query.prio_max = 100; query.query = "best"; query.datetime = DatetimeRange(Datetime(2009, 11, 11, 0, 0, 0), Datetime(2009, 11, 11, 0, 0, 0)); query.varcodes.insert(WR_VAR(0, 12, 101)); auto cur = db.query_data(query); wassert(actual(cur->remaining()) == 1); wassert(actual(cur->next()).istrue()); core::Record result; cur->to_record(result); wassert(actual(result.get("rep_memo")).istrue()); wassert(actual(result.enq("rep_memo", "")) == "tempship"); cur->discard_rest(); } }); add_method("query_repmemo_in_results", [](Fixture& f) { // Ensure that rep_memo is set in the results auto& db = *f.db; wassert(f.populate()); core::Record res; auto cur = db.query_data(core::Query()); while (cur->next()) { cur->to_record(res); wassert(actual(res["rep_memo"].isset()).istrue()); } }); } }; Tests tg1("db_misc_mem", nullptr, db::MEM); Tests tg2("db_misc_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg4("db_misc_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg6("db_misc_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg8("db_misc_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/mysql/0000755000175000017500000000000012653425050012572 500000000000000dballe-7.7/dballe/db/mysql/internals-test.cc0000644000175000017500000002240312652630043015775 00000000000000#include "core/tests.h" #include "internals.h" using namespace std; using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; namespace { struct ConnectorFixture : public Fixture { MySQLConnection conn; ConnectorFixture() { conn.open_test(); } void test_setup() { Fixture::test_setup(); conn.drop_table_if_exists("dballe_test"); conn.exec_no_data("CREATE TABLE dballe_test (val INTEGER NOT NULL)"); } }; class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("parse_url", [](Fixture& f) { // Test parsing urls mysql::ConnectInfo info; info.parse_url("mysql:"); wassert(actual(info.host) == ""); wassert(actual(info.user) == ""); wassert(actual(info.has_passwd).isfalse()); wassert(actual(info.passwd) == ""); wassert(actual(info.has_dbname).isfalse()); wassert(actual(info.dbname) == ""); wassert(actual(info.port) == 0); wassert(actual(info.unix_socket) == ""); info.parse_url("mysql://"); wassert(actual(info.host) == ""); wassert(actual(info.user) == ""); wassert(actual(info.has_passwd).isfalse()); wassert(actual(info.passwd) == ""); wassert(actual(info.has_dbname).isfalse()); wassert(actual(info.dbname) == ""); wassert(actual(info.port) == 0); wassert(actual(info.unix_socket) == ""); info.parse_url("mysql://localhost/"); wassert(actual(info.host) == "localhost"); wassert(actual(info.user) == ""); wassert(actual(info.has_passwd).isfalse()); wassert(actual(info.passwd) == ""); wassert(actual(info.has_dbname).isfalse()); wassert(actual(info.dbname) == ""); wassert(actual(info.port) == 0); wassert(actual(info.unix_socket) == ""); info.parse_url("mysql://localhost:1234/"); wassert(actual(info.host) == "localhost"); wassert(actual(info.user) == ""); wassert(actual(info.has_passwd).isfalse()); wassert(actual(info.passwd) == ""); wassert(actual(info.has_dbname).isfalse()); wassert(actual(info.dbname) == ""); wassert(actual(info.port) == 1234); wassert(actual(info.unix_socket) == ""); info.parse_url("mysql://localhost:1234/?user=enrico"); wassert(actual(info.host) == "localhost"); wassert(actual(info.user) == "enrico"); wassert(actual(info.has_passwd).isfalse()); wassert(actual(info.passwd) == ""); wassert(actual(info.has_dbname).isfalse()); wassert(actual(info.dbname) == ""); wassert(actual(info.port) == 1234); wassert(actual(info.unix_socket) == ""); info.parse_url("mysql://localhost:1234/foo?user=enrico"); wassert(actual(info.host) == "localhost"); wassert(actual(info.user) == "enrico"); wassert(actual(info.has_passwd).isfalse()); wassert(actual(info.passwd) == ""); wassert(actual(info.has_dbname).istrue()); wassert(actual(info.dbname) == "foo"); wassert(actual(info.port) == 1234); wassert(actual(info.unix_socket) == ""); info.parse_url("mysql://localhost:1234/foo?user=enrico&password=secret"); wassert(actual(info.host) == "localhost"); wassert(actual(info.user) == "enrico"); wassert(actual(info.has_passwd).istrue()); wassert(actual(info.passwd) == "secret"); wassert(actual(info.has_dbname).istrue()); wassert(actual(info.dbname) == "foo"); wassert(actual(info.port) == 1234); wassert(actual(info.unix_socket) == ""); info.parse_url("mysql://localhost/foo?user=enrico&password=secret"); wassert(actual(info.host) == "localhost"); wassert(actual(info.user) == "enrico"); wassert(actual(info.has_passwd).istrue()); wassert(actual(info.passwd) == "secret"); wassert(actual(info.has_dbname).istrue()); wassert(actual(info.dbname) == "foo"); wassert(actual(info.port) == 0); wassert(actual(info.unix_socket) == ""); info.parse_url("mysql:///foo?user=enrico&password=secret"); wassert(actual(info.host) == ""); wassert(actual(info.user) == "enrico"); wassert(actual(info.has_passwd).istrue()); wassert(actual(info.passwd) == "secret"); wassert(actual(info.has_dbname).istrue()); wassert(actual(info.dbname) == "foo"); wassert(actual(info.port) == 0); wassert(actual(info.unix_socket) == ""); }); add_method("query_int", [](Fixture& f) { // Test querying int values using namespace mysql; f.conn.exec_no_data("INSERT INTO dballe_test VALUES (1)"); f.conn.exec_no_data("INSERT INTO dballe_test VALUES (2)"); auto res = f.conn.exec_store("SELECT val FROM dballe_test"); int val = 0; unsigned count = 0; while (Row row = res.fetch()) { val += row.as_int(0); ++count; } wassert(actual(count) == 2); wassert(actual(val) == 3); }); add_method("query_int_null", [](Fixture& f) { // Test querying int values, with potential NULLs f.conn.drop_table_if_exists("dballe_testnull"); f.conn.exec_no_data("CREATE TABLE dballe_testnull (val INTEGER)"); f.conn.exec_no_data("INSERT INTO dballe_testnull VALUES (NULL)"); f.conn.exec_no_data("INSERT INTO dballe_testnull VALUES (42)"); auto res = f.conn.exec_store("SELECT val FROM dballe_testnull"); wassert(actual(res.rowcount()) == 2); int val = 0; unsigned count = 0; unsigned countnulls = 0; while (auto row = res.fetch()) { if (row.isnull(0)) ++countnulls; else val += row.as_int(0); ++count; } wassert(actual(val) == 42); wassert(actual(count) == 2); wassert(actual(countnulls) == 1); }); add_method("query_unsigned", [](Fixture& f) { // Test querying unsigned values f.conn.drop_table_if_exists("dballe_testbig"); f.conn.exec_no_data("CREATE TABLE dballe_testbig (val BIGINT)"); f.conn.exec_no_data("INSERT INTO dballe_testbig VALUES (0xFFFFFFFE)"); auto res = f.conn.exec_store("SELECT val FROM dballe_testbig"); wassert(actual(res.rowcount()) == 1); unsigned val = 0; unsigned count = 0; while (auto row = res.fetch()) { val += row.as_unsigned(0); ++count; } wassert(actual(val) == 0xFFFFFFFE); wassert(actual(count) == 1); }); add_method("query_unsigned_short", [](Fixture& f) { // Test querying unsigned short values char buf[200]; snprintf(buf, 200, "INSERT INTO dballe_test VALUES (%d)", (int)WR_VAR(3, 1, 12)); f.conn.exec_no_data(buf); auto res = f.conn.exec_store("SELECT val FROM dballe_test"); wassert(actual(res.rowcount()) == 1); Varcode val = 0; unsigned count = 0; while (auto row = res.fetch()) { val = (Varcode)row.as_int(0); ++count; } wassert(actual(count) == 1); wassert(actual(val) == WR_VAR(3, 1, 12)); }); add_method("has_tables", [](Fixture& f) { // Test has_tables wassert(actual(f.conn.has_table("this_should_not_exist")).isfalse()); wassert(actual(f.conn.has_table("dballe_test")).istrue()); }); add_method("settings", [](Fixture& f) { // Test settings f.conn.drop_table_if_exists("dballe_settings"); wassert(actual(f.conn.has_table("dballe_settings")).isfalse()); wassert(actual(f.conn.get_setting("test_key")) == ""); f.conn.set_setting("test_key", "42"); wassert(actual(f.conn.has_table("dballe_settings")).istrue()); wassert(actual(f.conn.get_setting("test_key")) == "42"); }); add_method("auto_increment", [](Fixture& f) { // Test auto_increment f.conn.drop_table_if_exists("dballe_testai"); f.conn.exec_no_data("CREATE TABLE dballe_testai (id INTEGER AUTO_INCREMENT PRIMARY KEY, val INTEGER)"); f.conn.exec_no_data("INSERT INTO dballe_testai (val) VALUES (42)"); wassert(actual(f.conn.get_last_insert_id()) == 1); f.conn.exec_no_data("INSERT INTO dballe_testai (val) VALUES (43)"); wassert(actual(f.conn.get_last_insert_id()) == 2); }); } } test("db_internals_mysql"); } dballe-7.7/dballe/db/mysql/repinfo.cc0000644000175000017500000001153312652630043014465 00000000000000/* * db/mysql/repinfo - repinfo table management * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "repinfo.h" #include "dballe/db/db.h" #include "dballe/db/querybuf.h" #include "dballe/db/mysql/internals.h" using namespace wreport; using namespace std; namespace dballe { namespace db { namespace mysql { MySQLRepinfoBase::MySQLRepinfoBase(MySQLConnection& conn) : Repinfo(conn), conn(conn) { read_cache(); } MySQLRepinfoBase::~MySQLRepinfoBase() { } void MySQLRepinfoBase::read_cache() { cache.clear(); memo_idx.clear(); auto res = conn.exec_store("SELECT id, memo, description, prio, descriptor, tablea FROM repinfo ORDER BY id"); while (auto row = res.fetch()) cache_append( row.as_int(0), row.as_cstring(1), row.as_cstring(2), row.as_int(3), row.as_cstring(4), row.as_int(5) ); // Rebuild the memo index as well rebuild_memo_idx(); } void MySQLRepinfoBase::insert_auto_entry(const char* memo) { auto res = conn.exec_store("SELECT MAX(id) FROM repinfo"); unsigned id = res.expect_one_result().as_unsigned(0); res = conn.exec_store("SELECT MAX(prio) FROM repinfo"); unsigned prio = res.expect_one_result().as_unsigned(0); ++id; ++prio; string escaped_memo = conn.escape(memo); Querybuf iq; iq.appendf(R"( INSERT INTO repinfo (id, memo, description, prio, descriptor, tablea) VALUES (%u, '%s', '%s', %u, '0', 255) )", id, escaped_memo.c_str(), escaped_memo.c_str(), prio); conn.exec_no_data(iq); } int MySQLRepinfoBase::id_use_count(unsigned id, const char* name) { Querybuf q; q.appendf("SELECT COUNT(1) FROM context WHERE id_report=%u", id); auto res = conn.exec_store(q); return res.expect_one_result().as_unsigned(0); } void MySQLRepinfoBase::delete_entry(unsigned id) { Querybuf q; q.appendf("DELETE FROM repinfo WHERE id=%u", id); conn.exec_no_data(q); } void MySQLRepinfoBase::update_entry(const sql::repinfo::Cache& entry) { Querybuf q; string escaped_memo = conn.escape(entry.new_memo); string escaped_desc = conn.escape(entry.new_desc); string escaped_descriptor = conn.escape(entry.new_descriptor); q.appendf(R"( UPDATE repinfo set memo='%s', description='%s', prio=%d, descriptor='%s', tablea=%u WHERE id=%u )", escaped_memo.c_str(), escaped_desc.c_str(), entry.new_prio, escaped_descriptor.c_str(), entry.new_tablea, entry.id); conn.exec_no_data(q); } void MySQLRepinfoBase::insert_entry(const sql::repinfo::Cache& entry) { Querybuf q; string escaped_memo = conn.escape(entry.new_memo); string escaped_desc = conn.escape(entry.new_desc); string escaped_descriptor = conn.escape(entry.new_descriptor); q.appendf(R"( INSERT INTO repinfo (id, memo, description, prio, descriptor, tablea) VALUES (%u, '%s', '%s', %d, '%s', %u) )", entry.id, escaped_memo.c_str(), escaped_desc.c_str(), entry.new_prio, escaped_descriptor.c_str(), entry.new_tablea); conn.exec_no_data(q); } void MySQLRepinfoBase::dump(FILE* out) { fprintf(out, "dump of table repinfo:\n"); fprintf(out, " id memo description prio desc tablea\n"); int count = 0; auto res = conn.exec_store("SELECT id, memo, description, prio, descriptor, tablea FROM repinfo ORDER BY id"); while (auto row = res.fetch()) { fprintf(out, " %4d %s %s %d %s %d\n", row.as_int(0), row.as_cstring(1), row.as_cstring(2), row.as_int(3), row.as_cstring(4), row.as_int(5)); ++count; } fprintf(out, "%d element%s in table repinfo\n", count, count != 1 ? "s" : ""); } MySQLRepinfoV6::MySQLRepinfoV6(MySQLConnection& conn) : MySQLRepinfoBase(conn) {} int MySQLRepinfoV6::id_use_count(unsigned id, const char* name) { Querybuf q; q.appendf("SELECT COUNT(1) FROM data WHERE id_report=%u", id); auto res = conn.exec_store(q); return res.expect_one_result().as_unsigned(0); } } } } dballe-7.7/dballe/db/mysql/levtr.h0000644000175000017500000000375712652630043014032 00000000000000/* * db/mysql/lev_tr - lev_tr table management * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_MYSQL_LEVTRV6_H #define DBALLE_DB_MYSQL_LEVTRV6_H #include #include #include #include #include namespace dballe { struct Record; struct Msg; namespace msg { struct Context; } namespace db { struct Connection; namespace mysql { struct DB; /** * Precompiled queries to manipulate the lev_tr table */ struct MySQLLevTrV6 : public sql::LevTr { protected: /// DB connection. MySQLConnection& conn; DBRow working_row; public: MySQLLevTrV6(MySQLConnection& conn); MySQLLevTrV6(const LevTr&) = delete; MySQLLevTrV6(const LevTr&&) = delete; MySQLLevTrV6& operator=(const MySQLLevTrV6&) = delete; ~MySQLLevTrV6(); /** * Return the ID for the given Level and Trange, adding it to the database * if it does not already exist */ int obtain_id(const Level& lev, const Trange& tr) override; const DBRow* read(int id) override; void read_all(std::function dest) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/mysql/driver.cc0000644000175000017500000001674012652630043014323 00000000000000/* * db/mysql/driver - Backend MySQL driver * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "driver.h" #include "internals.h" #include "repinfo.h" #include "station.h" #include "levtr.h" #include "datav6.h" #include "attrv6.h" #include "dballe/db/v6/qbuilder.h" #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { namespace mysql { Driver::Driver(MySQLConnection& conn) : conn(conn) { } Driver::~Driver() { } std::unique_ptr Driver::create_repinfov6() { return unique_ptr(new MySQLRepinfoV6(conn)); } std::unique_ptr Driver::create_stationv6() { return unique_ptr(new MySQLStationV6(conn)); } std::unique_ptr Driver::create_levtrv6() { return unique_ptr(new MySQLLevTrV6(conn)); } std::unique_ptr Driver::create_datav6() { return unique_ptr(new MySQLDataV6(conn)); } std::unique_ptr Driver::create_attrv6() { return unique_ptr(new MySQLAttrV6(conn)); } void Driver::run_built_query_v6( const v6::QueryBuilder& qb, std::function dest) { if (qb.bind_in_ident) throw error_unimplemented("binding in MySQL driver is not implemented"); sql::SQLRecordV6 rec; conn.exec_use(qb.sql_query, [&](const Row& row) { int output_seq = 0; if (qb.select_station) { rec.out_ana_id = row.as_int(output_seq++); rec.out_lat = row.as_int(output_seq++); rec.out_lon = row.as_int(output_seq++); if (row.isnull(output_seq)) { rec.out_ident_size = -1; rec.out_ident[0] = 0; } else { const char* ident = row.as_cstring(output_seq); rec.out_ident_size = min(strlen(ident), (string::size_type)63); memcpy(rec.out_ident, ident, rec.out_ident_size); rec.out_ident[rec.out_ident_size] = 0; } ++output_seq; } if (qb.select_varinfo) { rec.out_rep_cod = row.as_int(output_seq++); rec.out_id_ltr = row.as_int(output_seq++); rec.out_varcode = row.as_int(output_seq++); } if (qb.select_data_id) rec.out_id_data = row.as_int(output_seq++); if (qb.select_data) { rec.out_datetime = row.as_datetime(output_seq++); const char* value = row.as_cstring(output_seq++); unsigned val_size = min(strlen(value), (string::size_type)255); memcpy(rec.out_value, value, val_size); rec.out_value[val_size] = 0; } if (qb.select_summary_details) { rec.out_id_data = row.as_int(output_seq++); rec.out_datetime = row.as_datetime(output_seq++); rec.out_datetimemax = row.as_datetime(output_seq++); } dest(rec); }); } void Driver::create_tables_v6() { conn.exec_no_data(R"( CREATE TABLE station ( id INTEGER auto_increment PRIMARY KEY, lat INTEGER NOT NULL, lon INTEGER NOT NULL, ident CHAR(64), UNIQUE INDEX(lat, lon, ident(8)), INDEX(lon) ) ENGINE=InnoDB; )"); conn.exec_no_data(R"( CREATE TABLE repinfo ( id SMALLINT PRIMARY KEY, memo VARCHAR(20) NOT NULL, description VARCHAR(255) NOT NULL, prio INTEGER NOT NULL, descriptor CHAR(6) NOT NULL, tablea INTEGER NOT NULL, UNIQUE INDEX (prio), UNIQUE INDEX (memo) ) ENGINE=InnoDB; )"); conn.exec_no_data(R"( CREATE TABLE lev_tr ( id INTEGER auto_increment PRIMARY KEY, ltype1 INTEGER NOT NULL, l1 INTEGER NOT NULL, ltype2 INTEGER NOT NULL, l2 INTEGER NOT NULL, ptype INTEGER NOT NULL, p1 INTEGER NOT NULL, p2 INTEGER NOT NULL, UNIQUE INDEX (ltype1, l1, ltype2, l2, ptype, p1, p2) ) ENGINE=InnoDB; )"); conn.exec_no_data(R"( CREATE TABLE data ( id INTEGER auto_increment PRIMARY KEY, id_station SMALLINT NOT NULL, id_report INTEGER NOT NULL, id_lev_tr INTEGER NOT NULL, datetime DATETIME NOT NULL, id_var SMALLINT NOT NULL, value VARCHAR(255) NOT NULL, UNIQUE INDEX(id_station, datetime, id_lev_tr, id_report, id_var), INDEX(datetime), INDEX(id_lev_tr) ) ENGINE=InnoDB; )"); conn.exec_no_data(R"( CREATE TABLE attr ( id_data INTEGER NOT NULL, type SMALLINT NOT NULL, value VARCHAR(255) NOT NULL, UNIQUE INDEX (id_data, type) ) ENGINE=InnoDB; )"); } void Driver::delete_tables_v6() { conn.drop_table_if_exists("attr"); conn.drop_table_if_exists("data"); conn.drop_table_if_exists("lev_tr"); conn.drop_table_if_exists("repinfo"); conn.drop_table_if_exists("station"); conn.drop_settings(); } void Driver::vacuum_v6() { conn.exec_no_data("DELETE c FROM lev_tr c LEFT JOIN data d ON d.id_lev_tr = c.id WHERE d.id_lev_tr IS NULL"); conn.exec_no_data("DELETE p FROM station p LEFT JOIN data d ON d.id_station = p.id WHERE d.id IS NULL"); } void Driver::exec_no_data(const std::string& query) { conn.exec_no_data(query); } void Driver::explain(const std::string& query) { string explain_query = "EXPLAIN EXTENDED "; explain_query += query; fprintf(stderr, "%s\n", explain_query.c_str()); fprintf(stderr, "sid\tstype\ttable\ttype\tpos_ks\tkey\tkeylen\tref\trows\textra\n"); conn.exec_use(explain_query, [&](const Row& row) { fprintf(stderr, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", row.as_cstring(0), row.as_cstring(1), row.as_cstring(2), row.as_cstring(3), row.as_cstring(4), row.as_cstring(5), row.as_cstring(6), row.as_cstring(7), row.as_cstring(8), row.as_cstring(9)); // 0 id: 1 // 1 select_type: PRIMARY // 2 table: t1 // 3 type: index // 4 possible_keys: NULL // 5 key: PRIMARY // 6 key_len: 4 // 7 ref: NULL // 8 rows: 4 // 9 Extra: Using index }); fprintf(stderr, "level\tcode\tmessage\n"); conn.exec_use("SHOW WARNINGS", [&](const Row& row) { fprintf(stderr, "%s\t%s\t%s\n", row.as_cstring(0), row.as_cstring(1), row.as_cstring(2)); }); } } } } dballe-7.7/dballe/db/mysql/repinfo.h0000644000175000017500000000415012652630043014324 00000000000000/* * db/mysql/repinfo - repinfo table management * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_MYSQL_REPINFO_H #define DBALLE_DB_MYSQL_REPINFO_H #include #include #include #include namespace dballe { struct Record; namespace db { struct MySQLConnection; namespace mysql { /** * Fast cached access to the repinfo table */ struct MySQLRepinfoBase : public sql::Repinfo { /** * DB connection. The pointer is assumed always valid during the * lifetime of the object */ MySQLConnection& conn; MySQLRepinfoBase(MySQLConnection& conn); MySQLRepinfoBase(const MySQLRepinfoBase&) = delete; MySQLRepinfoBase(const MySQLRepinfoBase&&) = delete; virtual ~MySQLRepinfoBase(); MySQLRepinfoBase& operator=(const MySQLRepinfoBase&) = delete; void dump(FILE* out) override; protected: void delete_entry(unsigned id) override; void update_entry(const sql::repinfo::Cache& entry) override; void insert_entry(const sql::repinfo::Cache& entry) override; int id_use_count(unsigned id, const char* name) override; void read_cache() override; void insert_auto_entry(const char* memo) override; }; struct MySQLRepinfoV6 : public MySQLRepinfoBase { MySQLRepinfoV6(MySQLConnection& conn); protected: int id_use_count(unsigned id, const char* name) override; }; } } } #endif dballe-7.7/dballe/db/mysql/levtr.cc0000644000175000017500000000727712652630043014171 00000000000000#include "levtr.h" #include "dballe/core/defs.h" #include "dballe/db/querybuf.h" #include "dballe/msg/msg.h" #include #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace mysql { namespace { Level to_level(mysql::Row& row, int first_id=0) { return Level( row.as_int(first_id), row.as_int(first_id + 1), row.as_int(first_id + 2), row.as_int(first_id + 3)); } Trange to_trange(mysql::Row& row, int first_id=0) { return Trange( row.as_int(first_id), row.as_int(first_id + 1), row.as_int(first_id + 2)); } } MySQLLevTrV6::MySQLLevTrV6(MySQLConnection& conn) : conn(conn) { } MySQLLevTrV6::~MySQLLevTrV6() { } int MySQLLevTrV6::obtain_id(const Level& lev, const Trange& tr) { // Try select first Querybuf select; select.appendf(R"( SELECT id FROM lev_tr WHERE ltype1=%d AND l1=%d AND ltype2=%d AND l2=%d AND ptype=%d AND p1=%d AND p2=%d )", lev.ltype1, lev.l1, lev.ltype2, lev.l2, tr.pind, tr.p1, tr.p2); auto res = conn.exec_store(select); switch (res.rowcount()) { case 0: break; case 1: return res.fetch().as_int(0); default: error_consistency::throwf("select station ID query returned %u results", res.rowcount()); } // If not found, do an update Querybuf insert; insert.appendf( "INSERT INTO lev_tr (ltype1, l1, ltype2, l2, ptype, p1, p2) VALUES (%d, %d, %d, %d, %d, %d, %d)", lev.ltype1, lev.l1, lev.ltype2, lev.l2, tr.pind, tr.p1, tr.p2); conn.exec_no_data(insert); return conn.get_last_insert_id(); } const sql::LevTr::DBRow* MySQLLevTrV6::read(int id) { Querybuf select; select.appendf("SELECT ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr WHERE id=%d", id); auto res = conn.exec_store(select); bool found = false; while (auto row = res.fetch()) { working_row.id = id; working_row.ltype1 = row.as_int(0); working_row.l1 = row.as_int(1); working_row.ltype2 = row.as_int(2); working_row.l2 = row.as_int(3); working_row.pind = row.as_int(4); working_row.p1 = row.as_int(5); working_row.p2 = row.as_int(6); found = true; } if (!found) return nullptr; return &working_row; } void MySQLLevTrV6::read_all(std::function dest) { auto res = conn.exec_store("SELECT id, ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr"); while (auto row = res.fetch()) { working_row.id = row.as_int(0); working_row.ltype1 = row.as_int(1); working_row.l1 = row.as_int(2); working_row.ltype2 = row.as_int(3); working_row.l2 = row.as_int(4); working_row.pind = row.as_int(5); working_row.p1 = row.as_int(6); working_row.p2 = row.as_int(7); dest(working_row); } } void MySQLLevTrV6::dump(FILE* out) { int count = 0; fprintf(out, "dump of table lev_tr:\n"); fprintf(out, " id lev tr\n"); auto res = conn.exec_store("SELECT id, ltype1, l1, ltype2, l2, ptype, p1, p2 FROM lev_tr ORDER BY ID"); while (auto row = res.fetch()) { fprintf(out, " %4d ", row.as_int(0)); { stringstream str; str << to_level(row, 1); fprintf(out, "%-20s ", str.str().c_str()); } { stringstream str; str << to_trange(row, 5); fprintf(out, "%-10s\n", str.str().c_str()); } ++count; } fprintf(out, "%d element%s in table lev_tr\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/mysql/internals.h0000644000175000017500000002636712652630043014677 00000000000000/* * db/mysql/internals - Implementation infrastructure for the MySQL DB connection * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_MYSQL_INTERNALS_H #define DBALLE_DB_MYSQL_INTERNALS_H #include #include #include #include namespace dballe { namespace db { struct MySQLStatement; /** * Report a MySQL error */ struct error_mysql : public db::error { std::string msg; /** * Copy informations from the ODBC diagnostic record to the dba error * report */ error_mysql(MYSQL* db, const std::string& msg); error_mysql(const std::string& dbmsg, const std::string& msg); ~error_mysql() throw () {} wreport::ErrorCode code() const throw () { return wreport::WR_ERR_ODBC; } virtual const char* what() const throw () { return msg.c_str(); } static void throwf(MYSQL* db, const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3); }; namespace mysql { struct ConnectInfo { std::string host; std::string user; bool has_passwd = false; std::string passwd; bool has_dbname = false; std::string dbname; unsigned port = 0; std::string unix_socket; // Reset everything to defaults void reset(); void parse_url(const std::string& url); // Modeled after http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html std::string to_url() const; }; struct Row { MYSQL_RES* res = nullptr; MYSQL_ROW row = nullptr; Row(MYSQL_RES* res, MYSQL_ROW row) : res(res), row(row) {} operator bool() const { return row != nullptr; } operator MYSQL_ROW() { return row; } operator const MYSQL_ROW() const { return row; } int as_int(unsigned col) const { return strtol(row[col], 0, 10); } unsigned as_unsigned(unsigned col) const { return strtoul(row[col], 0, 10); } const char* as_cstring(unsigned col) const { return row[col]; } std::string as_string(unsigned col) const { return std::string(row[col], mysql_fetch_lengths(res)[col]); } Datetime as_datetime(int col) const; bool isnull(unsigned col) const { return row[col] == nullptr; } }; struct Result { MYSQL_RES* res = nullptr; Result() : res(nullptr) {} Result(MYSQL_RES* res) : res(res) {} ~Result() { if (res) mysql_free_result(res); } /// Implement move Result(Result&& o) : res(o.res) { o.res = nullptr; } Result& operator=(Result&& o) { if (this == &o) return *this; if (res) mysql_free_result(res); res = o.res; o.res = nullptr; return *this; } operator bool() const { return res != nullptr; } operator MYSQL_RES*() { return res; } operator const MYSQL_RES*() const { return res; } unsigned rowcount() const { return mysql_num_rows(res); } unsigned colcount() const { return mysql_num_fields(res); } /// Check that the function returned only one row, and return that row. Row expect_one_result(); /** * Fetch one row. * * Note: mysql_fetch_row does not reset the error indicator, so there is no * way to tell the end of the iteration from an error. As a consequence, * this is only safe to call after a mysql_store_result. * * Accessing mysql_use_result results is implemented using execute_fetch. */ Row fetch() { return Row(res, mysql_fetch_row(res)); } // Prevent copy Result(const Result&) = delete; Result& operator=(const Result&) = delete; }; } /// Database connection class MySQLConnection : public Connection { protected: /// Database connection MYSQL* db = nullptr; void send_result(mysql::Result&& res, std::function dest); protected: void init_after_connect(); // See https://dev.mysql.com/doc/refman/5.0/en/mysql-real-connect.html void open(const mysql::ConnectInfo& info); public: MySQLConnection(); MySQLConnection(const MySQLConnection&) = delete; MySQLConnection(const MySQLConnection&&) = delete; ~MySQLConnection(); MySQLConnection& operator=(const MySQLConnection&) = delete; MySQLConnection& operator=(const MySQLConnection&&) = delete; operator MYSQL*() { return db; } // See http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html void open_url(const std::string& url); void open_test(); /// Escape a C string std::string escape(const char* str); /// Escape a string std::string escape(const std::string& str); /** * Run a query throwing no exceptions, warning on stderr if it is not * successful or if it gives a nonempty result */ void exec_no_data_nothrow(const char* query) noexcept; // Run a query, checking that it is successful and it gives no results void exec_no_data(const char* query); // Run a query, checking that it is successful and it gives no results void exec_no_data(const std::string& query); // Run a query, with a locally stored result mysql::Result exec_store(const char* query); // Run a query, with a locally stored result mysql::Result exec_store(const std::string& query); // Run a query, with a remotely fetched result void exec_use(const char* query, std::function dest); // Run a query, with a remotely fetched result void exec_use(const std::string& query, std::function dest); std::unique_ptr transaction() override; /// Check if the database contains a table bool has_table(const std::string& name) override; /** * Get a value from the settings table. * * Returns the empty string if the table does not exist. */ std::string get_setting(const std::string& key) override; /** * Set a value in the settings table. * * The table is created if it does not exist. */ void set_setting(const std::string& key, const std::string& value) override; /// Drop the settings table void drop_settings() override; /** * Delete a table in the database if it exists, otherwise do nothing. */ void drop_table_if_exists(const char* name); /** * Return LAST_INSERT_ID or LAST_INSER_ROWID or whatever is appropriate for * the current database, if supported. * * If not supported, an exception is thrown. */ int get_last_insert_id(); /// Count the number of rows modified by the last query that was run //int changes(); #if 0 /// Wrap sqlite3_exec, without a callback void wrap_sqlite3_exec(const std::string& query); void wrap_sqlite3_exec_nothrow(const std::string& query) noexcept; #endif }; #if 0 /// MySQL statement struct MySQLStatement { MySQLConnection& conn; sqlite3_stmt *stm = nullptr; MySQLStatement(MySQLConnection& conn, const std::string& query); MySQLStatement(const MySQLStatement&) = delete; MySQLStatement(const MySQLStatement&&) = delete; ~MySQLStatement(); MySQLStatement& operator=(const MySQLStatement&) = delete; /** * Bind all the arguments in a single invocation. * * Note that the parameter positions are used as bind column numbers, so * calling this function twice will re-bind columns instead of adding new * ones. */ template void bind(const Args& ...args) { bindn(args...); } void bind_null_val(int idx); void bind_val(int idx, int val); void bind_val(int idx, unsigned val); void bind_val(int idx, unsigned short val); void bind_val(int idx, const Datetime& val); void bind_val(int idx, const char* val); // Warning: SQLITE_STATIC is used void bind_val(int idx, const std::string& val); // Warning: SQLITE_STATIC is used /// Run the query, ignoring all results void execute(); /** * Run the query, calling on_row for every row in the result. * * At the end of the function, the statement is reset, even in case an * exception is thrown. */ void execute(std::function on_row); /** * Run the query, raising an error if there is more than one row in the * result */ void execute_one(std::function on_row); /// Read the int value of a column in the result set (0-based) int column_int(int col) { return sqlite3_column_int(stm, col); } /// Read the int value of a column in the result set (0-based) sqlite3_int64 column_int64(int col) { return sqlite3_column_int64(stm, col); } /// Read the double value of a column in the result set (0-based) double column_double(int col) { return sqlite3_column_double(stm, col); } /// Read the string value of a column in the result set (0-based) const char* column_string(int col) { return (const char*)sqlite3_column_text(stm, col); } /// Read the string value of a column and parse it as a Datetime Datetime column_datetime(int col); /// Check if a column has a NULL value (0-based) bool column_isnull(int col) { return sqlite3_column_type(stm, col) == SQLITE_NULL; } void wrap_sqlite3_reset(); void wrap_sqlite3_reset_nothrow() noexcept; /** * Get the current error message, reset the statement and throw * error_sqlite */ [[noreturn]] void reset_and_throw(const std::string& errmsg); operator sqlite3_stmt*() { return stm; } #if 0 /// @return SQLExecute's result int execute(); /// @return SQLExecute's result int exec_direct(const char* query); /// @return SQLExecute's result int exec_direct(const char* query, int qlen); /// @return SQLExecute's result int execute_and_close(); /// @return SQLExecute's result int exec_direct_and_close(const char* query); /// @return SQLExecute's result int exec_direct_and_close(const char* query, int qlen); /** * @return the number of columns in the result set (or 0 if the statement * did not return columns) */ int columns_count(); bool fetch(); bool fetch_expecting_one(); void close_cursor(); void close_cursor_if_needed(); /// Row count for select operations size_t select_rowcount(); /// Row count for insert, delete and other non-select operations size_t rowcount(); #endif private: // Implementation of variadic bind: terminating condition template void bindn() {} // Implementation of variadic bind: recursive iteration over the parameter pack template void bindn(const T& first, const Args& ...args) { bind_val(total - sizeof...(args), first); bindn(args...); } }; #endif } } #endif dballe-7.7/dballe/db/mysql/driver.h0000644000175000017500000000337612652630043014166 00000000000000/* * db/mysql/driver - Backend MySQL driver * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_MYSQL_DRIVER_H #define DBALLE_DB_MYSQL_DRIVER_H #include namespace dballe { namespace db { struct MySQLConnection; namespace mysql { struct Driver : public sql::Driver { MySQLConnection& conn; Driver(MySQLConnection& conn); virtual ~Driver(); std::unique_ptr create_repinfov6() override; std::unique_ptr create_stationv6() override; std::unique_ptr create_levtrv6() override; std::unique_ptr create_datav6() override; std::unique_ptr create_attrv6() override; void run_built_query_v6(const v6::QueryBuilder& qb, std::function dest) override; void create_tables_v6() override; void delete_tables_v6() override; void vacuum_v6() override; void exec_no_data(const std::string& query) override; void explain(const std::string& query) override; }; } } } #endif dballe-7.7/dballe/db/mysql/station.cc0000644000175000017500000001511412652630043014503 00000000000000#include "station.h" #include "dballe/db/mysql/internals.h" #include "dballe/db/querybuf.h" #include "dballe/core/var.h" #include "dballe/record.h" #include using namespace wreport; using namespace dballe::db; using namespace std; namespace dballe { namespace db { namespace mysql { MySQLStationBase::MySQLStationBase(MySQLConnection& conn) : conn(conn) { } MySQLStationBase::~MySQLStationBase() { } bool MySQLStationBase::maybe_get_id(int lat, int lon, const char* ident, int* id) { Querybuf qb; MySQLStatement* s; if (ident) { string escaped_ident = conn.escape(ident); qb.appendf("SELECT id FROM station WHERE lat=%d AND lon=%d AND ident='%s'", lat, lon, escaped_ident.c_str()); } else { qb.appendf("SELECT id FROM station WHERE lat=%d AND lon=%d AND ident IS NULL", lat, lon); } auto res = conn.exec_store(qb); switch (res.rowcount()) { case 0: return false; case 1: *id = res.fetch().as_int(0); return true; default: error_consistency::throwf("select station ID query returned %u results", res.rowcount()); } } int MySQLStationBase::get_id(int lat, int lon, const char* ident) { int id; if (maybe_get_id(lat, lon, ident, &id)) return id; throw error_notfound("station not found in the database"); } int MySQLStationBase::obtain_id(int lat, int lon, const char* ident, bool* inserted) { // Try select first int id; if (maybe_get_id(lat, lon, ident, &id)) { if (inserted) *inserted = false; return id; } // Not found, do an insert Querybuf qb; if (ident) { string escaped_ident = conn.escape(ident); qb.appendf(R"( INSERT INTO station (lat, lon, ident) VALUES (%d, %d, '%s') )", lat, lon, escaped_ident.c_str()); } else { qb.appendf(R"( INSERT INTO station (lat, lon, ident) VALUES (%d, %d, NULL) )", lat, lon); } conn.exec_no_data(qb); if (inserted) *inserted = true; return conn.get_last_insert_id(); #if 0 // See http://mikefenwick.com/blog/insert-into-database-or-return-id-of-duplicate-row-in-mysql/ // // It would be nice to use this, BUT at every failed insert the // auto_increment sequence is updated, so every lookup causes a hole in the // sequence. // // Since the auto_increment sequence blocks all inserts once it runs out of // numbers, we cannot afford to eat it away for every ID lookup. // // http://stackoverflow.com/questions/2615417/what-happens-when-auto-increment-on-integer-column-reaches-the-max-value-in-data // Just in case there's any question, the AUTO_INCREMENT field /DOES NOT // WRAP/. Once you hit the limit for the field size, INSERTs generate an // error. (As per Jeremy Cole) Querybuf qb; if (ident) { string escaped_ident = conn.escape(ident); qb.appendf(R"( INSERT INTO station (lat, lon, ident) VALUES (%d, %d, '%s') ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id) )", lat, lon, escaped_ident.c_str()); } else { qb.appendf(R"( INSERT INTO station (lat, lon, ident) VALUES (%d, %d, NULL) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id) )", lat, lon); } conn.exec_no_data(qb); if (inserted) *inserted = mysql_affected_rows(conn) > 0; return conn.get_last_insert_id(); #endif } void MySQLStationBase::read_station_vars(const std::string& query, std::function)> dest) { // Retrieve results Varcode last_varcode = 0; unique_ptr var; auto res = conn.exec_store(query); while (auto row = res.fetch()) { Varcode code = row.as_int(0); TRACE("fill_ana_layer Got B%02ld%03ld %s\n", WR_VAR_X(code), WR_VAR_Y(code), out_value); // First process the variable, possibly inserting the old one in the message if (last_varcode != code) { TRACE("fill_ana_layer new var\n"); if (var.get()) { TRACE("fill_ana_layer inserting old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } var = newvar(code, row.as_cstring(1)); last_varcode = code; } if (!row.isnull(2)) { TRACE("fill_ana_layer new attribute\n"); var->seta(newvar(row.as_int(2), row.as_cstring(3))); } } if (var.get()) { TRACE("fill_ana_layer inserting leftover old var B%02d%03d\n", WR_VAR_X(var->code()), WR_VAR_Y(var->code())); dest(move(var)); } } void MySQLStationBase::get_station_vars(int id_station, int id_report, std::function)> dest) { // Perform the query Querybuf query; query.appendf(R"( SELECT d.id_var, d.value, a.type, a.value FROM data d LEFT JOIN attr a ON a.id_data = d.id WHERE d.id_station=%d AND d.id_report=%d AND d.id_lev_tr = -1 ORDER BY d.id_var, a.type )", id_station, id_report); TRACE("fill_ana_layer Performing query: %s with idst %d idrep %d\n", query.c_str(), id_station, id_report); read_station_vars(query, dest); } void MySQLStationBase::dump(FILE* out) { int count = 0; fprintf(out, "dump of table station:\n"); auto res = conn.exec_store("SELECT id, lat, lon, ident FROM station"); while (auto row = res.fetch()) { fprintf(out, " %d, %.5f, %.5f", row.as_int(0), row.as_int(1) / 100000.0, row.as_int(2) / 100000.0); if (row.isnull(3)) putc('\n', out); else fprintf(out, ", %s\n", row.as_cstring(3)); ++count; } fprintf(out, "%d element%s in table station\n", count, count != 1 ? "s" : ""); } void MySQLStationBase::add_station_vars(int id_station, Record& rec) { Querybuf query; query.appendf(R"( SELECT d.id_var, d.value FROM data d, repinfo ri WHERE d.id_lev_tr = -1 AND ri.id = d.id_report AND d.id_station = %d AND ri.prio=( SELECT MAX(sri.prio) FROM repinfo sri JOIN data sd ON sri.id=sd.id_report WHERE sd.id_station=d.id_station AND sd.id_lev_tr = -1 AND sd.id_var=d.id_var) )", id_station); auto res = conn.exec_store(query); while (auto row = res.fetch()) rec.set(newvar((Varcode)row.as_int(0), row.as_cstring(1))); } MySQLStationV6::MySQLStationV6(MySQLConnection& conn) : MySQLStationBase(conn) {} } } } dballe-7.7/dballe/db/mysql/datav6.cc0000644000175000017500000001116712652630043014213 00000000000000// Verify that nothing has been deleted #include "datav6.h" #include "dballe/db/sql.h" #include "dballe/db/querybuf.h" #include "dballe/db/v6/qbuilder.h" #include "dballe/record.h" #include #include using namespace wreport; using namespace std; namespace dballe { namespace db { namespace mysql { MySQLDataV6::MySQLDataV6(MySQLConnection& conn) : conn(conn) { } MySQLDataV6::~MySQLDataV6() { } void MySQLDataV6::insert(Transaction& t, sql::bulk::InsertV6& vars, UpdateMode update_mode) { // Get the current status of variables for this context Querybuf select; select.appendf(R"( SELECT id, id_lev_tr, id_var, value FROM data WHERE id_station=%d AND id_report=%d AND datetime='%04d-%02d-%02d %02d:%02d:%02d' ORDER BY id_lev_tr, id_var )", vars.id_station, vars.id_report, vars.datetime.year, vars.datetime.month, vars.datetime.day, vars.datetime.hour, vars.datetime.minute, vars.datetime.second); // Scan the result in parallel with the variable list, annotating changed // items with their data ID sql::bulk::AnnotateVarsV6 todo(vars); auto select_res = conn.exec_store(select); while (auto row = select_res.fetch()) { todo.annotate( row.as_int(0), row.as_int(1), row.as_int(2), row.as_cstring(3)); } todo.annotate_end(); // We now have a todo-list switch (update_mode) { case UPDATE: if (todo.do_update) { for (auto& v: vars) { if (!v.needs_update()) continue; string escaped_value = conn.escape(v.var->enqc()); Querybuf update; update.appendf("UPDATE data SET value='%s' WHERE id=%d", escaped_value.c_str(), v.id_data); conn.exec_no_data(update); v.set_updated(); } } break; case IGNORE: break; case ERROR: if (todo.do_update) throw error_consistency("refusing to overwrite existing data"); } if (todo.do_insert) { for (auto& v: vars) { if (!v.needs_insert()) continue; string escaped_value = conn.escape(v.var->enqc()); Querybuf insert(512); insert.appendf(R"( INSERT INTO data (id_station, id_report, id_lev_tr, datetime, id_var, value) VALUES (%d, %d, %d, '%04d-%02d-%02d %02d:%02d:%02d', %d, '%s') )", vars.id_station, vars.id_report, v.id_levtr, vars.datetime.year, vars.datetime.month, vars.datetime.day, vars.datetime.hour, vars.datetime.minute, vars.datetime.second, v.var->code(), escaped_value.c_str()); conn.exec_no_data(insert); v.id_data = conn.get_last_insert_id(); v.set_inserted(); } } } void MySQLDataV6::remove(const v6::QueryBuilder& qb) { if (qb.bind_in_ident) throw error_unimplemented("binding in MySQL driver is not implemented"); Querybuf dq(512); dq.append("DELETE FROM data WHERE id IN ("); dq.start_list(","); bool found = false; auto res = conn.exec_store(qb.sql_query); while (auto row = res.fetch()) { // Note: if the query gets too long, we can split this in more DELETE // runs dq.append_list(row.as_cstring(0)); found = true; } dq.append(")"); if (found) conn.exec_no_data(dq); } void MySQLDataV6::dump(FILE* out) { int count = 0; fprintf(out, "dump of table data:\n"); fprintf(out, " id st rep ltr datetime var\n"); auto res = conn.exec_store("SELECT id, id_station, id_report, id_lev_tr, datetime, id_var, value FROM data"); while (auto row = res.fetch()) { int id_lev_tr = row.as_int(3); const char* datetime = row.as_cstring(4); Varcode code = row.as_int(5); char ltr[20]; if (id_lev_tr == -1) strcpy(ltr, "----"); else snprintf(ltr, 20, "%04d", id_lev_tr); fprintf(out, " %4d %4d %3d %s %s %01d%02d%03d", row.as_int(0), row.as_int(1), row.as_int(2), ltr, datetime, WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code)); if (row.isnull(6)) fprintf(out, "\n"); else fprintf(out, " %s\n", row.as_cstring(6)); ++count; } fprintf(out, "%d element%s in table data\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/mysql/attrv6.cc0000644000175000017500000001040112652630043014242 00000000000000/* * db/mysql/attrv6 - attribute table management * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "attrv6.h" #include "dballe/db/sql/internals.h" #include "dballe/db/querybuf.h" #include "dballe/var.h" using namespace std; using namespace wreport; namespace dballe { namespace db { namespace mysql { MySQLAttrV6::MySQLAttrV6(MySQLConnection& conn) : conn(conn) { } MySQLAttrV6::~MySQLAttrV6() { } void MySQLAttrV6::insert(Transaction& t, sql::bulk::InsertAttrsV6& attrs, UpdateMode update_mode) { Querybuf select_query; select_query.append("SELECT id_data, type, value FROM attr WHERE id_data IN ("); select_query.start_list(","); int last_data_id = -1; for (const auto& a: attrs) { if (a.id_data == last_data_id) continue; select_query.append_listf("%d", a.id_data); last_data_id = a.id_data; } select_query.append(") ORDER BY id_data, type"); // Get the current status of variables for this context sql::bulk::AnnotateAttrsV6 todo(attrs); auto select_res = conn.exec_store(select_query); while (auto row = select_res.fetch()) { todo.annotate( row.as_int(0), row.as_int(1), row.as_cstring(2)); } todo.annotate_end(); // We now have a todo-list switch (update_mode) { case UPDATE: if (todo.do_update) { for (auto& a: attrs) { if (!a.needs_update()) continue; string escaped_value = conn.escape(a.attr->enqc()); Querybuf update; update.appendf("UPDATE attr SET value='%s' WHERE id_data=%d AND type=%d", escaped_value.c_str(), a.id_data, (int)a.attr->code()); conn.exec_no_data(update); a.set_updated(); } } break; case IGNORE: break; case ERROR: if (todo.do_update) throw error_consistency("refusing to overwrite existing data"); } if (todo.do_insert) { Querybuf insert(512); insert.append("INSERT INTO attr (id_data, type, value) VALUES "); insert.start_list(","); for (auto& a: attrs) { if (!a.needs_insert()) continue; string escaped_value = conn.escape(a.attr->enqc()); insert.append_listf("(%d, %d, '%s')", a.id_data, (int)a.attr->code(), escaped_value.c_str()); a.set_inserted(); } conn.exec_no_data(insert); } } void MySQLAttrV6::read(int id_data, function)> dest) { Querybuf q; q.appendf("SELECT type, value FROM attr WHERE id_data=%d", id_data); auto res = conn.exec_store(q); while (auto row = res.fetch()) { if (row.isnull(1)) dest(newvar(row.as_int(0))); else dest(newvar(row.as_int(0), row.as_cstring(1))); } } void MySQLAttrV6::dump(FILE* out) { int count = 0; fprintf(out, "dump of table attr:\n"); auto res = conn.exec_store("SELECT id_data, type, value FROM attr"); while (auto row = res.fetch()) { Varcode type = row.as_int(1); fprintf(out, " %4d, %01d%02d%03d", row.as_int(0), WR_VAR_F(type), WR_VAR_X(type), WR_VAR_Y(type)); if (row.isnull(2)) fprintf(out, "\n"); else fprintf(out, " %s\n", row.as_cstring(2)); ++count; } fprintf(out, "%d element%s in table attr\n", count, count != 1 ? "s" : ""); } } } } dballe-7.7/dballe/db/mysql/internals.cc0000644000175000017500000004267012652630043015030 00000000000000/* * db/mysql/internals - Implementation infrastructure for the MySQL DB connection * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "internals.h" #include "dballe/core/vasprintf.h" #include "dballe/db/querybuf.h" #include #include #include #include using namespace std; using namespace wreport; namespace dballe { namespace db { error_mysql::error_mysql(MYSQL* db, const std::string& msg) { this->msg = msg; this->msg += ":"; this->msg += mysql_error(db); } error_mysql::error_mysql(const std::string& dbmsg, const std::string& msg) { this->msg = msg; this->msg += ":"; this->msg += dbmsg; } void error_mysql::throwf(MYSQL* db, const char* fmt, ...) { // Format the arguments va_list ap; va_start(ap, fmt); char* cmsg; vasprintf(&cmsg, fmt, ap); va_end(ap); // Convert to string std::string msg(cmsg); free(cmsg); throw error_mysql(db, msg); } namespace mysql { struct URLParser { const std::string& url; ConnectInfo& dest; URLParser(const std::string& url, ConnectInfo& dest) : url(url), dest(dest) {} void trace(const char* name, std::string::size_type beg, std::string::size_type end) const { //fprintf(stderr, "TRACE %s: %s %zd--%zd: %.*s\n", url.c_str(), name, beg, end, (int)(end - beg), url.c_str() + beg); } // Return a substring of url between positions [beg, end) std::string cut(std::string::size_type beg, std::string::size_type end) { trace("cut", beg, end); return url.substr(beg, end - beg); } void parse() { trace(" *** parse", 0, url.size()); if (url == "mysql:" || url == "mysql://" || url == "mysql:///") return; if (url.substr(0, 8) != "mysql://") error_consistency::throwf("MySQL connect URL '%s' does not start with mysql://", url.c_str()); size_t hostport_end = url.find('/', 8); if (hostport_end == string::npos) error_consistency::throwf("MySQL connect URL '%s' does not end the host:port part with a slash", url.c_str()); parse_hostport(8, hostport_end); size_t qstring_start = url.find('?', hostport_end + 1); if (qstring_start == string::npos) { if (hostport_end + 1 < url.size()) { dest.has_dbname = true; dest.dbname = cut(hostport_end + 1, url.size()); } } else { if (hostport_end + 1 < qstring_start) { dest.has_dbname = true; dest.dbname = cut(hostport_end + 1, qstring_start); } parse_qstring(qstring_start, url.size()); } } #if 0 string buf(url + 7); size_t pos = buf.find('@'); if (pos == string::npos) { return connect(buf.c_str(), "", ""); // odbc://dsn } // Split the string at '@' string userpass = buf.substr(0, pos); string dsn = buf.substr(pos + 1); pos = userpass.find(':'); if (pos == string::npos) { return connect(dsn.c_str(), userpass.c_str(), ""); // odbc://user@dsn } string user = userpass.substr(0, pos); string pass = userpass.substr(pos + 1); connect(dsn.c_str(), user.c_str(), pass.c_str()); // odbc://user:pass@dsn #endif // Parse host:port part of the URL void parse_hostport(std::string::size_type beg, std::string::size_type end) { trace("parse_hostport", beg, end); size_t port = url.find(':', beg); if (port == string::npos) dest.host = cut(beg, end); else { dest.host = cut(beg, port); dest.port = stoul(cut(port + 1, end)); } } void parse_qstring(std::string::size_type beg, std::string::size_type end) { trace("parse_qstring", beg, end); while (true) { // Skip leading ? or & ++beg; size_t next = url.find('&', beg); if (next == string::npos) { // Last element parse_qstring_keyval(beg, end); break; } else { parse_qstring_keyval(beg, next); beg = next; } } } void parse_qstring_keyval(std::string::size_type beg, std::string::size_type end) { trace("parse_qstring_keyval", beg, end); size_t assign = url.find('=', beg); if (assign == string::npos) handle_keyval(cut(beg, end), string()); else handle_keyval(cut(beg, assign), cut(assign + 1, end)); } void handle_keyval(const std::string& key, const std::string& val) { if (key == "user") dest.user = val; else if (key == "password") { dest.has_passwd = true; dest.passwd = val; } } }; void ConnectInfo::reset() { host.clear(); user.clear(); has_passwd = false; passwd.clear(); has_dbname = false; dbname.clear(); port = 0; unix_socket.clear(); } void ConnectInfo::parse_url(const std::string& url) { // mysql://[host][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]... reset(); URLParser parser(url, *this); parser.parse(); } std::string ConnectInfo::to_url() const { std::string res = "mysql://"; if (!user.empty() || !passwd.empty()) { res += user; if (has_passwd) res += ":" + passwd; res += "@"; } res += host; if (port != 0) res += ":" + to_string(port); res += "/" + dbname; // TODO: currently unsupported unix_socket; return res; } Datetime Row::as_datetime(int col) const { Datetime res; sscanf(as_cstring(col), "%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu", &res.year, &res.month, &res.day, &res.hour, &res.minute, &res.second); return res; } Row Result::expect_one_result() { if (mysql_num_rows(res) != 1) error_consistency::throwf("query returned %u rows instead of 1", (unsigned)mysql_num_rows(res)); return Row(res, mysql_fetch_row(res)); } } MySQLConnection::MySQLConnection() { db = mysql_init(nullptr); // mysql_error does seem to work with nullptr as its argument. I only saw // it return empty strings, though, because I have not been able to find a // way to make mysql_int fail for real if (!db) throw error_mysql(nullptr, "failed to create a MYSQL object"); } MySQLConnection::~MySQLConnection() { if (db) mysql_close(db); } void MySQLConnection::open(const mysql::ConnectInfo& info) { // See http://www.enricozini.org/2012/tips/sa-sqlmode-traditional/ mysql_options(db, MYSQL_INIT_COMMAND, "SET sql_mode='traditional'"); // TODO: benchmark with and without compression //mysql_options(db, MYSQL_OPT_COMPRESS, 0); // Auto-reconnect transparently messes up all assumptions, so we switch it // off: see https://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html my_bool reconnect = 0; mysql_options(db, MYSQL_OPT_RECONNECT, &reconnect); if (!mysql_real_connect(db, info.host.empty() ? nullptr : info.host.c_str(), info.user.c_str(), info.has_passwd ? info.passwd.c_str() : nullptr, info.dbname.c_str(), info.port, info.unix_socket.empty() ? nullptr : info.unix_socket.c_str(), CLIENT_REMEMBER_OPTIONS)) throw error_mysql(db, "cannot open MySQL connection to " + info.to_url()); init_after_connect(); } void MySQLConnection::open_url(const std::string& url) { using namespace mysql; this->url = url; ConnectInfo info; info.parse_url(url); open(info); } void MySQLConnection::open_test() { const char* envurl = getenv("DBA_DB_MYSQL"); if (envurl == NULL) throw error_consistency("DBA_DB_MYSQL not defined"); return open_url(envurl); } void MySQLConnection::init_after_connect() { server_type = ServerType::MYSQL; // autocommit is off by default when inside a transaction // set_autocommit(false); } std::string MySQLConnection::escape(const char* str) { // Dirty: we write directly inside the resulting std::string storage. // It should work in C++11, although not according to its specifications, // and if for some reason we discover that it does not work, this can be // rewritten with one extra string copy. size_t str_len = strlen(str); string res(str_len * 2 + 1, 0); unsigned long len = mysql_real_escape_string(db, const_cast(res.data()), str, str_len); res.resize(len); return res; } std::string MySQLConnection::escape(const std::string& str) { // Dirty: we write directly inside the resulting std::string storage. // It should work in C++11, although not according to its specifications, // and if for some reason we discover that it does not work, this can be // rewritten with one extra string copy. string res(str.size() * 2 + 1, 0); unsigned long len = mysql_real_escape_string(db, const_cast(res.data()), str.data(), str.size()); res.resize(len); return res; } void MySQLConnection::exec_no_data_nothrow(const char* query) noexcept { using namespace mysql; if (mysql_query(db, query)) { fprintf(stderr, "cannot execute '%s': %s", query, mysql_error(db)); return; } MYSQL_RES* res = mysql_store_result(db); if (res != nullptr) { fprintf(stderr, "query '%s' returned %u rows instead of zero", query, (unsigned)mysql_num_rows(res)); mysql_free_result(res); return; } if (mysql_errno(db)) { fprintf(stderr, "cannot store result of query '%s': %s", query, mysql_error(db)); mysql_free_result(res); return; } } void MySQLConnection::exec_no_data(const char* query) { using namespace mysql; if (mysql_query(db, query)) error_mysql::throwf(db, "cannot execute '%s'", query); Result res(mysql_store_result(db)); if (res) error_consistency::throwf("query '%s' returned %u rows instead of zero", query, (unsigned)mysql_num_rows(res)); else if (mysql_errno(db)) error_mysql::throwf(db, "cannot store result of query '%s'", query); } void MySQLConnection::exec_no_data(const std::string& query) { using namespace mysql; if (mysql_real_query(db, query.data(), query.size())) error_mysql::throwf(db, "cannot execute '%s'", query.c_str()); Result res(mysql_store_result(db)); if (res) error_consistency::throwf("query '%s' returned %u rows instead of zero", query.c_str(), (unsigned)mysql_num_rows(res)); else if (mysql_errno(db)) error_mysql::throwf(db, "cannot store result of query '%s'", query.c_str()); } mysql::Result MySQLConnection::exec_store(const char* query) { using namespace mysql; if (mysql_query(db, query)) error_mysql::throwf(db, "cannot execute '%s'", query); Result res(mysql_store_result(db)); if (res) return res; if (mysql_errno(db)) error_mysql::throwf(db, "cannot store result of query '%s'", query); else error_consistency::throwf("query '%s' returned no data", query); } mysql::Result MySQLConnection::exec_store(const std::string& query) { using namespace mysql; if (mysql_real_query(db, query.data(), query.size())) error_mysql::throwf(db, "cannot execute '%s'", query.c_str()); Result res(mysql_store_result(db)); if (res) return res; if (mysql_errno(db)) error_mysql::throwf(db, "cannot store result of query '%s'", query.c_str()); else error_consistency::throwf("query '%s' returned no data", query.c_str()); } void MySQLConnection::exec_use(const char* query, std::function dest) { using namespace mysql; if (mysql_query(db, query)) error_mysql::throwf(db, "cannot execute '%s'", query); Result res(mysql_use_result(db)); if (!res) { if (mysql_errno(db)) error_mysql::throwf(db, "cannot store result of query '%s'", query); else error_consistency::throwf("query '%s' returned no data", query); } send_result(move(res), dest); } void MySQLConnection::exec_use(const std::string& query, std::function dest) { using namespace mysql; if (mysql_real_query(db, query.data(), query.size())) error_mysql::throwf(db, "cannot execute '%s'", query.c_str()); Result res(mysql_use_result(db)); if (!res) { if (mysql_errno(db)) error_mysql::throwf(db, "cannot store result of query '%s'", query.c_str()); else error_consistency::throwf("query '%s' returned no data", query.c_str()); } send_result(move(res), dest); } void MySQLConnection::send_result(mysql::Result&& res, std::function dest) { using namespace mysql; while (Row row = res.fetch()) { try { dest(row); } catch (...) { // If dest throws an exception, we still need to flush the inbound // rows before rethrowing it: this is not done automatically when // closing the result, and not doing it will break the next // queries. // // fetch() will not throw exceptions (see its documentation) // because mysql_fetch_row has no usable error reporting. // If there is a network connectivity problem, we will never know it. // // See: https://dev.mysql.com/doc/refman/5.0/en/mysql-use-result.html // «When using mysql_use_result(), you must execute // mysql_fetch_row() until a NULL value is returned, otherwise, // the unfetched rows are returned as part of the result set for // your next query. The C API gives the error 'Commands out of // sync; you can't run this command now' if you forget to do // this!» while (res.fetch()) ; throw; } } } struct MySQLTransaction : public Transaction { MySQLConnection& conn; bool fired = false; MySQLTransaction(MySQLConnection& conn) : conn(conn) { } ~MySQLTransaction() { if (!fired) rollback_nothrow(); } void commit() override { conn.exec_no_data("COMMIT"); fired = true; } void rollback() override { conn.exec_no_data("ROLLBACK"); fired = true; } void rollback_nothrow() noexcept { conn.exec_no_data_nothrow("ROLLBACK"); fired = true; } void lock_table(const char* name) override { // https://dev.mysql.com/doc/refman/5.0/en/lock-tables-and-transactions.html // LOCK TABLES is not transaction-safe and implicitly commits any active transaction before attempting to lock the tables. // // So we do nothing here, and pray that MySQL's default transaction // isolation is enough to prevent most concurrency problems. } }; std::unique_ptr MySQLConnection::transaction() { exec_no_data("BEGIN"); return unique_ptr(new MySQLTransaction(*this)); } void MySQLConnection::drop_table_if_exists(const char* name) { exec_no_data(string("DROP TABLE IF EXISTS ") + name); } int MySQLConnection::get_last_insert_id() { return mysql_insert_id(db); } bool MySQLConnection::has_table(const std::string& name) { using namespace mysql; string query = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='" + name + "'"; Result res(exec_store(query)); Row row = res.expect_one_result(); return row.as_unsigned(0) > 0; } std::string MySQLConnection::get_setting(const std::string& key) { using namespace mysql; if (!has_table("dballe_settings")) return string(); string query = "SELECT value FROM dballe_settings WHERE `key`='"; query += escape(key); query += '\''; Result res(exec_store(query)); if (res.rowcount() == 0) return string(); if (res.rowcount() > 1) error_consistency::throwf("got %d results instead of 1 executing %s", res.rowcount(), query.c_str()); Row row = res.fetch(); return row.as_string(0); } void MySQLConnection::set_setting(const std::string& key, const std::string& value) { if (!has_table("dballe_settings")) exec_no_data("CREATE TABLE dballe_settings (`key` CHAR(64) NOT NULL PRIMARY KEY, value CHAR(64) NOT NULL)"); string query = "INSERT INTO dballe_settings (`key`, value) VALUES ('"; query += escape(key); query += "', '"; query += escape(value); query += "') ON DUPLICATE KEY UPDATE value=VALUES(value)"; exec_no_data(query); } void MySQLConnection::drop_settings() { drop_table_if_exists("dballe_settings"); } } } dballe-7.7/dballe/db/mysql/station.h0000644000175000017500000000564512652630043014355 00000000000000/* * db/mysql/station - station table management * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_MYSQL_STATION_H #define DBALLE_DB_MYSQL_STATION_H /** @file * @ingroup db * * Station table management used by the db module. */ #include #include #include namespace wreport { struct Var; } namespace dballe { namespace db { struct MySQLConnection; namespace mysql { /** * Precompiled queries to manipulate the station table */ class MySQLStationBase : public sql::Station { protected: /** * DB connection. */ MySQLConnection& conn; /// Lookup the ID of a station, returning true if it was found, false if not bool maybe_get_id(int lat, int lon, const char* ident, int* id); /// Run stm, read its output and generate variables to send to dest void read_station_vars(const std::string& query, std::function)> dest); public: MySQLStationBase(MySQLConnection& conn); ~MySQLStationBase(); MySQLStationBase(const MySQLStationBase&) = delete; MySQLStationBase(const MySQLStationBase&&) = delete; MySQLStationBase& operator=(const MySQLStationBase&) = delete; /** * Get the station ID given latitude, longitude and mobile identifier. * * It throws an exception if it does not exist. * * @return * Resulting ID of the station */ int get_id(int lat, int lon, const char* ident=nullptr) override; /** * Get the station ID given latitude, longitude and mobile identifier. * * It creates the station record if it does not exist. * * @return * Resulting ID of the station */ int obtain_id(int lat, int lon, const char* ident=nullptr, bool* inserted=NULL) override; void get_station_vars(int id_station, int id_report, std::function)> dest) override; void add_station_vars(int id_station, Record& rec) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; class MySQLStationV6 : public MySQLStationBase { public: MySQLStationV6(MySQLConnection& conn); }; } } } #endif dballe-7.7/dballe/db/mysql/attrv6.h0000644000175000017500000000371712652630043014120 00000000000000/* * db/mysql/attr - attribute table management * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_MYSQL_ATTRV6_H #define DBALLE_DB_MYSQL_ATTRV6_H #include #include namespace dballe { namespace db { namespace mysql { /** * Precompiled queries to manipulate the attr table */ class MySQLAttrV6 : public sql::AttrV6 { protected: /** DB connection. */ MySQLConnection& conn; public: MySQLAttrV6(MySQLConnection& conn); MySQLAttrV6(const MySQLAttrV6&) = delete; MySQLAttrV6(const MySQLAttrV6&&) = delete; MySQLAttrV6& operator=(const MySQLAttrV6&) = delete; ~MySQLAttrV6(); void insert(Transaction& t, sql::bulk::InsertAttrsV6& vars, UpdateMode update_mode=UPDATE) override; /** * Load from the database all the attributes for var * * @param var * wreport::Var to which the resulting attributes will be added * @return * The error indicator for the function (See @ref error.h) */ void read(int id_data, std::function)> dest) override; /** * Dump the entire contents of the table to an output stream */ void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/mysql/datav6.h0000644000175000017500000000327612652630043014057 00000000000000/* * db/mysql/data - data table management * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_MYSQL_V6_DATA_H #define DBALLE_DB_MYSQL_V6_DATA_H /** @file * @ingroup db * * Data table management used by the db module. */ #include #include namespace dballe { struct Record; namespace db { namespace mysql { struct DB; /** * Precompiled query to manipulate the data table */ class MySQLDataV6 : public sql::DataV6 { protected: /** DB connection. */ MySQLConnection& conn; public: MySQLDataV6(MySQLConnection& conn); MySQLDataV6(const MySQLDataV6&) = delete; MySQLDataV6(const MySQLDataV6&&) = delete; MySQLDataV6& operator=(const MySQLDataV6&) = delete; ~MySQLDataV6(); void insert(Transaction& t, sql::bulk::InsertV6& vars, UpdateMode update_mode=UPDATE) override; void remove(const v6::QueryBuilder& qb) override; void dump(FILE* out) override; }; } } } #endif dballe-7.7/dballe/db/trace.h0000644000175000017500000000601712652630043012617 00000000000000/* * dballe/db/trace - Trace and measure DB queries * * Copyright (C) 2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_DB_TRACE_H #define DBALLE_DB_TRACE_H #include #include #include #include #include #include #include namespace dballe { struct Query; namespace db { class TraceOp; class Trace { protected: // Command line used to start the current process std::vector argv; // Process ID of the current process (cached getpid() result) pid_t pid; // Database connection URL std::string db_url; // JSON output buffer, holding one JSON record std::stringstream json_buf; // JSON serializer core::JSONWriter writer; // Output file name std::string out_fname; // Output file FILE* out = 0; // Populate argv void read_argv(); // Cancel the current output, resetting json_buf void output_abort(); // Flush the current output, then reset json_buf void output_flush(); public: typedef std::unique_ptr Tracer; Trace(); ~Trace(); Tracer trace_connect(const std::string& url); Tracer trace_reset(const char* repinfo_file=0); Tracer trace_remove_station_data(const Query& query); Tracer trace_remove(const Query& query); Tracer trace_remove_all(); Tracer trace_vacuum(); Tracer trace_query_stations(const Query& query); Tracer trace_query_station_data(const Query& query); Tracer trace_query_data(const Query& query); Tracer trace_query_summary(const Query& query); Tracer trace_export_msgs(const Query& query); friend class TraceOp; }; class TraceOp { protected: Trace* trace = 0; clock_t start; public: TraceOp(); TraceOp(Trace& trace, const char* operation); ~TraceOp(); void done(); template void add_list(const char* key, const T& val) { trace->writer.add(key); trace->writer.add_list(val); } void add_null(const char* key) { trace->writer.add(key); trace->writer.add_null(); } template void add(const char* key, const T& val) { trace->writer.add(key); trace->writer.add(val); } void add_query(const Query& query); }; } } #endif dballe-7.7/dballe/db/db-query-summary-test.cc0000644000175000017500000002771712652630043016071 00000000000000#include "config.h" #include "db/tests.h" using namespace dballe; using namespace dballe::db; using namespace dballe::tests; using namespace wreport; using namespace std; namespace { struct DBData : public TestDataSet { DBData() { stations["st1_synop"].info.coords = Coords(12.34560, 76.54320); stations["st1_synop"].info.report = "synop"; stations["st1_synop"].values.set(newvar("B07030", 42.0)); // height stations["st1_metar"].info = stations["st1_synop"].info; stations["st1_metar"].info.report = "metar"; stations["st1_metar"].values.set(newvar("block", 1)); stations["st1_metar"].values.set(newvar("station", 2)); stations["st1_metar"].values.set(newvar("B07030", 50.0)); // height stations["st2_temp"].info.coords = Coords(23.45670, 65.43210); stations["st2_temp"].info.report = "temp"; stations["st2_temp"].values.set(newvar("B07030", 100.0)); // height stations["st2_metar"].info = stations["st2_temp"].info; stations["st2_metar"].info.report = "metar"; stations["st2_metar"].values.set(newvar("block", 3)); stations["st2_metar"].values.set(newvar("station", 4)); stations["st2_metar"].values.set(newvar("B07030", 110.0)); // height data["rec1a"].info = stations["st1_metar"].info; data["rec1a"].info.datetime = Datetime(1945, 4, 25, 8); data["rec1a"].info.level = Level(10, 11, 15, 22); data["rec1a"].info.trange = Trange(20, 111, 122); data["rec1a"].values.set("B12101", 290.0); data["rec1a"].values.set("B12103", 280.0); data["rec1b"] = data["rec1a"]; data["rec1b"].info.datetime = Datetime(1945, 4, 26, 8); data["rec1b"].values.set("B12101", 291.0); data["rec1b"].values.set("B12103", 281.0); data["rec2a"].info = stations["st2_metar"].info; data["rec2a"].info.datetime = Datetime(1945, 4, 25, 8); data["rec2a"].info.level = Level(10, 11, 15, 22); data["rec2a"].info.trange = Trange(20, 111, 122); data["rec2a"].values.set("B12101", 300.0); data["rec2a"].values.set("B12103", 298.0); data["rec2b"] = data["rec2a"]; data["rec2b"].info.datetime = Datetime(1945, 4, 26, 8); data["rec2b"].values.set("B12101", 301.0); data["rec2b"].values.set("B12103", 291.0); } }; struct Fixture : public DBFixture { using DBFixture::DBFixture; int st1_id; int st2_id; void test_setup() { DBFixture::test_setup(); DBData dbdata; wassert(populate_database(dbdata)); st1_id = dbdata.stations["st1_metar"].info.ana_id; st2_id = dbdata.stations["st2_metar"].info.ana_id; } }; std::string parm(const char* name, int val) { stringstream out; out << name << "=" << val; return out.str(); } class Tests : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { add_method("query_ana_id", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query(parm("ana_id", f.st1_id), 2)); wassert(actual(db).try_summary_query(parm("ana_id", f.st2_id), 2)); wassert(actual(db).try_summary_query(parm("ana_id", (f.st1_id + f.st2_id) * 2), 0)); }); #if 0 // TODO: summary of station vars is not supported at the moment, waiting for a use case for it add_method("query_station_vars", [](Fixture& f) { auto& db = *f.db; core::Query query; query.query_station_vars = true; auto cur = db.query_summary(query); ensure_equals(cur->test_iterate(), 8); }); #endif add_method("query_year", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("year=1001", 0)); wassert(actual(db).try_summary_query("yearmin=1999", 0)); auto check_base = [](const vector& res) { wassert(actual(res[0].enq("lat", MISSING_INT)) == 1234560); wassert(actual(res[0].enq("lon", MISSING_INT)) == 7654320); wassert(actual(res[0].get_level()) == Level(10, 11, 15, 22)); wassert(actual(res[0].get_trange()) == Trange(20, 111, 122)); wassert(actual(res[0].enq("var", "")) == "B12101"); }; auto check_nodetails = [&](const vector& res) { wassert(check_base(res)); wassert(actual(res[0].isset("context_id")).isfalse()); wassert(actual(res[0].isset("yearmin")).isfalse()); wassert(actual(res[0].isset("yearmax")).isfalse()); }; auto check_details = [&](const vector& res) { wassert(check_base(res)); wassert(actual(res[0].enq("context_id", MISSING_INT)) == 2); DatetimeRange dtr = res[0].get_datetimerange(); wassert(actual(dtr.min) == Datetime(1945, 4, 25, 8)); wassert(actual(dtr.max) == Datetime(1945, 4, 26, 8)); }; wassert(actual(db).try_summary_query("yearmin=1945", 4, check_nodetails)); wassert(actual(db).try_summary_query("yearmin=1945, query=details", 4, check_details)); wassert(actual(db).try_summary_query("yearmax=1944", 0)); wassert(actual(db).try_summary_query("yearmax=1945", 4)); wassert(actual(db).try_summary_query("yearmax=2030", 4)); wassert(actual(db).try_summary_query("year=1944", 0)); wassert(actual(db).try_summary_query("year=1945", 4)); wassert(actual(db).try_summary_query("year=1946", 0)); }); add_method("query_blockstation", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("B01001=1", 2)); wassert(actual(db).try_summary_query("B01001=2", 0)); wassert(actual(db).try_summary_query("B01002=3", 0)); wassert(actual(db).try_summary_query("B01002=4", 2)); }); add_method("query_ana_filter", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("ana_filter=block=1", 2)); wassert(actual(db).try_summary_query("ana_filter=B01001=1", 2)); wassert(actual(db).try_summary_query("ana_filter=block>1", 2)); wassert(actual(db).try_summary_query("ana_filter=B01001>1", 2)); wassert(actual(db).try_summary_query("ana_filter=block<=1", 2)); wassert(actual(db).try_summary_query("ana_filter=B01001>3", 0)); wassert(actual(db).try_summary_query("ana_filter=B01001>=3", 2)); wassert(actual(db).try_summary_query("ana_filter=B01001<=1", 2)); wassert(actual(db).try_summary_query("ana_filter=0<=B01001<=2", 2)); wassert(actual(db).try_summary_query("ana_filter=1<=B01001<=1", 2)); wassert(actual(db).try_summary_query("ana_filter=2<=B01001<=4", 2)); wassert(actual(db).try_summary_query("ana_filter=4<=B01001<=6", 0)); }); add_method("query_data_filter", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("data_filter=B12101<300.0", 1)); wassert(actual(db).try_summary_query("data_filter=B12101<=300.0", 2)); wassert(actual(db).try_summary_query("data_filter=B12101=300.0", 1)); wassert(actual(db).try_summary_query("data_filter=B12101>=300,0", 1)); wassert(actual(db).try_summary_query("data_filter=B12101>300.0", 1)); wassert(actual(db).try_summary_query("data_filter=B12101<400.0", 2)); wassert(actual(db).try_summary_query("data_filter=B12101<=400.0", 2)); wassert(actual(db).try_summary_query("data_filter=B12102>400.0", 0)); }); add_method("query_lat_lon", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("latmin=11.0", 4)); wassert(actual(db).try_summary_query("latmin=12.34560", 4)); wassert(actual(db).try_summary_query("latmin=13.0", 2)); wassert(actual(db).try_summary_query("latmax=11.0", 0)); wassert(actual(db).try_summary_query("latmax=12.34560", 2)); wassert(actual(db).try_summary_query("latmax=13.0", 2)); wassert(actual(db).try_summary_query("lonmin=75., lonmax=77.", 2)); wassert(actual(db).try_summary_query("lonmin=76.54320, lonmax=76.54320", 2)); wassert(actual(db).try_summary_query("lonmin=76.54330, lonmax=77.", 0)); wassert(actual(db).try_summary_query("lonmin=77., lonmax=76.54310", 2)); wassert(actual(db).try_summary_query("lonmin=77., lonmax=76.54320", 4)); wassert(actual(db).try_summary_query("lonmin=77., lonmax=-10", 0)); }); add_method("query_mobile", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("mobile=0", 4)); wassert(actual(db).try_summary_query("mobile=1", 0)); }); add_method("query_ident", [](Fixture& f) { //auto& db = *f.db; // TODO: add mobile stations to the fixture so we can query ident }); add_method("query_timerange", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("pindicator=20", 4)); wassert(actual(db).try_summary_query("pindicator=21", 0)); wassert(actual(db).try_summary_query("p1=111", 4)); wassert(actual(db).try_summary_query("p1=112", 0)); wassert(actual(db).try_summary_query("p2=121", 0)); wassert(actual(db).try_summary_query("p2=122", 4)); wassert(actual(db).try_summary_query("p2=123", 0)); }); add_method("query_level", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("leveltype1=10", 4)); wassert(actual(db).try_summary_query("leveltype1=11", 0)); wassert(actual(db).try_summary_query("leveltype2=15", 4)); wassert(actual(db).try_summary_query("leveltype2=16", 0)); wassert(actual(db).try_summary_query("l1=11", 4)); wassert(actual(db).try_summary_query("l1=12", 0)); wassert(actual(db).try_summary_query("l2=22", 4)); wassert(actual(db).try_summary_query("l2=23", 0)); }); add_method("query_var", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("var=B01001", 0)); wassert(actual(db).try_summary_query("var=B12101", 2)); wassert(actual(db).try_summary_query("var=B12102", 0)); }); add_method("query_rep_memo", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("rep_memo=synop", 0)); wassert(actual(db).try_summary_query("rep_memo=metar", 4)); wassert(actual(db).try_summary_query("rep_memo=temp", 0)); }); add_method("query_priority", [](Fixture& f) { auto& db = *f.db; wassert(actual(db).try_summary_query("priority=101", 0)); wassert(actual(db).try_summary_query("priority=81", 4)); wassert(actual(db).try_summary_query("priority=102", 0)); wassert(actual(db).try_summary_query("priomin=70", 4)); wassert(actual(db).try_summary_query("priomin=80", 4)); wassert(actual(db).try_summary_query("priomin=90", 0)); wassert(actual(db).try_summary_query("priomax=70", 0)); wassert(actual(db).try_summary_query("priomax=81", 4)); wassert(actual(db).try_summary_query("priomax=100", 4)); }); } }; Tests tg1("db_query_summary_mem", nullptr, db::MEM); Tests tg2("db_query_summary_v6_sqlite", "SQLITE", db::V6); #ifdef HAVE_ODBC Tests tg4("db_query_summary_v6_odbc", "ODBC", db::V6); #endif #ifdef HAVE_LIBPQ Tests tg6("db_query_summary_v6_postgresql", "POSTGRESQL", db::V6); #endif #ifdef HAVE_MYSQL Tests tg8("db_query_summary_v6_mysql", "MYSQL", db::V6); #endif } dballe-7.7/dballe/db/db.h0000644000175000017500000004206212652630043012106 00000000000000#ifndef DBALLE_DB_H #define DBALLE_DB_H #include #include #include #include #include #include #include #include /** @file * @ingroup db * * Functions used to connect to DB-All.e and insert, query and delete data. */ namespace dballe { struct Record; struct Query; struct Values; struct StationValues; struct DataValues; struct Message; struct Messages; struct DB; namespace db { struct Connection; struct ODBCConnection; /** * Simple typedef to make typing easier */ typedef std::vector AttrList; /// Common interface for all kinds of cursors struct Cursor { virtual ~Cursor(); /// Get the database that created this cursor virtual DB& get_db() const = 0; /** * Get the number of rows still to be fetched * * @return * The number of rows still to be queried. The value is undefined if no * query has been successfully peformed yet using this cursor. */ virtual int remaining() const = 0; /** * Get a new item from the results of a query * * @returns * true if a new record has been read, false if there is no more data to read */ virtual bool next() = 0; /// Discard the results that have not been read yet virtual void discard_rest() = 0; /** * Fill in a record with the contents of a dba_db_cursor * * @param rec * The record where to store the values */ virtual void to_record(Record& rec) = 0; /// Get the station identifier virtual int get_station_id() const = 0; /// Get the station latitude virtual double get_lat() const = 0; /// Get the station longitude virtual double get_lon() const = 0; /// Get the station identifier, or NULL if missing virtual const char* get_ident(const char* def=0) const = 0; /// Get the report name virtual const char* get_rep_memo() const = 0; /** * Iterate the cursor until the end, returning the number of items. * * If dump is a FILE pointer, also dump the cursor values to it */ virtual unsigned test_iterate(FILE* dump=0); }; /// Cursor iterating over stations struct CursorStation : public Cursor { }; /// Common interface for cursors iterating over station or data values struct CursorValue : public Cursor { /// Get the variable code virtual wreport::Varcode get_varcode() const = 0; /// Get the variable virtual wreport::Var get_var() const = 0; /** * Return an integer value that can be used to refer to the current * variable for attribute access */ virtual int attr_reference_id() const = 0; }; /// Cursor iterating over station data values struct CursorStationData : public CursorValue { }; /// Cursor iterating over data values struct CursorData : public CursorValue { /// Get the level virtual Level get_level() const = 0; /// Get the time range virtual Trange get_trange() const = 0; /// Get the datetime virtual Datetime get_datetime() const = 0; }; /// Cursor iterating over summary entries struct CursorSummary : public Cursor { /// Get the level virtual Level get_level() const = 0; /// Get the time range virtual Trange get_trange() const = 0; /// Get the variable code virtual wreport::Varcode get_varcode() const = 0; /// Get the datetime range virtual DatetimeRange get_datetimerange() const = 0; /// Get the count of elements virtual size_t get_count() const = 0; }; #if 0 /** * Query attributes for the current variable */ virtual void query_attrs(std::function&&)> dest) = 0; /** * Insert/overwrite new attributes for the current variable * * @param attrs * The attributes to be added */ virtual void attr_insert(const Values& attrs) = 0; /** * Delete attributes for the current variable * * @param qcs * Array of WMO codes of the attributes to delete. If empty, all attributes * associated to id_data will be deleted. */ virtual void attr_remove(const AttrList& qcs) = 0; #endif } class DB { public: virtual ~DB(); static db::Format get_default_format(); static void set_default_format(db::Format format); /** * Start a session with DB-All.e * * @param dsn * The ODBC DSN of the database to use * @param user * The user name to use to connect to the DSN * @param password * The password to use to connect to the DSN. To specify an empty password, * pass "" or NULL * @return * The new DB object */ static std::unique_ptr connect(const char* dsn, const char* user, const char* password); /** * Create from a SQLite file pathname * * @param pathname * The pathname to a SQLite file */ static std::unique_ptr connect_from_file(const char* pathname); /** * Create from an url-like specification, that can be: * * @l sqlite:[//]foo.sqlite * @l odbc://[user[:pass]@]dsn * @l test:[//] * * @param url * The url-like connection descriptor */ static std::unique_ptr connect_from_url(const char* url); /** * Create an in-memory database */ static std::unique_ptr connect_memory(const std::string& arg = std::string()); /** * Start a test session with DB-All.e * * Take information from the environment (@see dba_db_create_from_env) and * default to ./test.sqlite if nothing is specified. */ static std::unique_ptr connect_test(); /** * Create a database from an open Connection */ static std::unique_ptr create(std::unique_ptr conn); /** * Return TRUE if the string looks like a DB URL * * @param str * The string to test * @return * true if it looks like a URL, else false */ static bool is_url(const char* str); /// Return the format of this DB virtual db::Format format() const = 0; /** * Remove all our traces from the database, if applicable. * * After this has been called, all other DB methods except for reset() will * fail. */ virtual void disappear() = 0; /** * Reset the database, removing all existing Db-All.e tables and re-creating them * empty. * * @param repinfo_file * The name of the CSV file with the report type information data to load. * The file is in CSV format with 6 columns: report code, mnemonic id, * description, priority, descriptor, table A category. * If repinfo_file is NULL, then the default of /etc/dballe/repinfo.csv is * used. */ virtual void reset(const char* repinfo_file=0) = 0; /** * Update the repinfo table in the database, with the data found in the given * file. * * @param repinfo_file * The name of the CSV file with the report type information data to load. * The file is in CSV format with 6 columns: report code, mnemonic id, * description, priority, descriptor, table A category. * If repinfo_file is NULL, then the default of /etc/dballe/repinfo.csv is * used. * @retval added * The number of repinfo entries that have been added * @retval deleted * The number of repinfo entries that have been deleted * @retval updated * The number of repinfo entries that have been updated */ virtual void update_repinfo(const char* repinfo_file, int* added, int* deleted, int* updated) = 0; /** * Get a mapping between rep_memo and their priorities */ virtual std::map get_repinfo_priorities() = 0; public: /** * Insert station values into the database * * The IDs of the station andl all variables that were inserted will be * stored in vals. * * @param vals * The values to insert. * @param can_replace * If true, then existing data can be rewritten, else data can only be added. * @param station_can_add * If false, it will not create a missing station record, and only data * for existing stations can be added. If true, then if we are inserting * data for a station that does not yet exists in the database, it will * be created. */ virtual void insert_station_data(StationValues& vals, bool can_replace, bool station_can_add) = 0; /** * Insert data values into the database * * The IDs of the station andl all variables that were inserted will be * stored in vals. * * @param vals * The values to insert. * @param can_replace * If true, then existing data can be rewritten, else data can only be added. * @param station_can_add * If false, it will not create a missing station record, and only data * for existing stations can be added. If true, then if we are inserting * data for a station that does not yet exists in the database, it will * be created. */ virtual void insert_data(DataValues& vals, bool can_replace, bool station_can_add) = 0; /** * Remove data from the database * * @param rec * The record with the query data (see technical specifications, par. 1.6.4 * "parameter output/input") to select the items to be deleted */ virtual void remove_station_data(const Query& query) = 0; /** * Remove data from the database * * @param rec * The record with the query data (see technical specifications, par. 1.6.4 * "parameter output/input") to select the items to be deleted */ virtual void remove(const Query& rec) = 0; /** * Remove all data from the database. * * This is faster than remove() with an empty record, and unlike reset() it * preserves existing report information. */ virtual void remove_all() = 0; /** * Perform database cleanup operations. * * Orphan values are currently: * \li context values for which no data exists * \li station values for which no context exists * * Depending on database size, this routine can take a few minutes to execute. */ virtual void vacuum() = 0; /** * Start a query on the station variables archive. * * The cursor will iterate over unique lat, lon, ident triples, and will * contain all station vars. If a station var exists twice on two different * networks, only one will be present: the one of the network with the * highest priority. * * @param query * The record with the query data (see @ref dba_record_keywords) * @return * The cursor to use to iterate over the results */ virtual std::unique_ptr query_stations(const Query& query) = 0; /** * Query the station variables in the database. * * When multiple values per variable are present, the results will be presented * in increasing order of priority. * * @param query * The record with the query data (see technical specifications, par. 1.6.4 * "parameter output/input") * @return * The cursor to use to iterate over the results */ virtual std::unique_ptr query_station_data(const Query& query) = 0; /** * Query the database. * * When multiple values per variable are present, the results will be presented * in increasing order of priority. * * @param query * The record with the query data (see technical specifications, par. 1.6.4 * "parameter output/input") * @return * The cursor to use to iterate over the results */ virtual std::unique_ptr query_data(const Query& query) = 0; /** * Query a summary of what the result would be for a query. * * @param query * The record with the query data (see technical specifications, par. 1.6.4 * "parameter output/input") * @return * The cursor to use to iterate over the results. The results are the * same as query_data, except that no context_id, datetime and value are * provided, so it only gives all the available combinations of data * contexts. */ virtual std::unique_ptr query_summary(const Query& query) = 0; /** * Query attributes on a station value * * @param data_id * The id (returned by Cursor::attr_reference_id()) used to refer to the value * @param dest * The function that will be called on each resulting attribute */ virtual void attr_query_station(int data_id, std::function)>&& dest) = 0; /** * Query attributes on a data value * * @param data_id * The id (returned by Cursor::attr_reference_id()) used to refer to the value * @param dest * The function that will be called on each resulting attribute */ virtual void attr_query_data(int data_id, std::function)>&& dest) = 0; /** * Insert new attributes on a station value * * @param data_id * The id (returned by Cursor::attr_reference_id()) used to refer to the value * @param attrs * The attributes to be added */ virtual void attr_insert_station(int data_id, const Values& attrs) = 0; /** * Insert new attributes on a data value * * @param data_id * The id (returned by Cursor::attr_reference_id()) used to refer to the value * @param attrs * The attributes to be added */ virtual void attr_insert_data(int data_id, const Values& attrs) = 0; /** * Delete attributes from a station value * * @param data_id * The id (returned by Cursor::attr_reference_id()) used to refer to the value * @param qcs * Array of WMO codes of the attributes to delete. If empty, all attributes * associated to the value will be deleted. */ virtual void attr_remove_station(int data_id, const db::AttrList& qcs) = 0; /** * Delete attributes from a data value * * @param data_id * The id (returned by Cursor::attr_reference_id()) used to refer to the value * @param qcs * Array of WMO codes of the attributes to delete. If empty, all attributes * associated to the value will be deleted. */ virtual void attr_remove_data(int data_id, const db::AttrList& qcs) = 0; /** * Check if this varcode and data_id correspond to a station variable. This * is used only to implement attr_* functions to be used when this * information is not known. A database for which this information is not * relevant (for example, in v6 databases there is a single ID space for * station and data variable) can return any arbitrary value, since later * they will be ignored. * * This should disappear once client APIs start making a distinction * between attributes in station variables and attributes on data * variables. */ virtual bool is_station_variable(int data_id, wreport::Varcode varcode) = 0; /** * Import a Message into the DB-All.e database * * @param db * The DB-All.e database to write the data into * @param msg * The Message containing the data to import * @param repmemo * Report mnemonic to which imported data belong. If NULL is passed, then it * will be chosen automatically based on the message type. * @param flags * Customise different aspects of the import process. It is a bitmask of the * various DBA_IMPORT_* macros. */ virtual void import_msg(const Message& msg, const char* repmemo, int flags) = 0; /** * Import Messages into the DB-All.e database * * @param db * The DB-All.e database to write the data into * @param msgs * The Messages containing the data to import * @param repmemo * Report mnemonic to which imported data belong. If NULL is passed, then it * will be chosen automatically based on the message type. * @param flags * Customise different aspects of the import process. It is a bitmask of the * various DBA_IMPORT_* macros. */ virtual void import_msgs(const Messages& msgs, const char* repmemo, int flags); /** * Perform the query in `query', and send the results to dest. * * Return false from dest to interrupt the query. * * @param query * The query to perform * @param dest * The function that will handle the resulting messages * @returns true if the query reached its end, false if it got interrupted * because dest returned false. */ virtual bool export_msgs(const Query& query, std::function&&)> dest) = 0; /** * Dump the entire contents of the database to an output stream */ virtual void dump(FILE* out) = 0; /// Return the default repinfo file pathname static const char* default_repinfo_file(); }; } /* vim:set ts=4 sw=4: */ #endif dballe-7.7/dballe/benchmark/0000755000175000017500000000000012653425050012772 500000000000000dballe-7.7/dballe/benchmark/bench-main.cc0000644000175000017500000000020512652630043015216 00000000000000#include int main (int argc, const char* argv[]) { wreport::benchmark::Registry::basic_run(argc, argv); } dballe-7.7/dballe/core/0000755000175000017500000000000012653425050011770 500000000000000dballe-7.7/dballe/core/defs-test.cc0000644000175000017500000000504512652630043014120 00000000000000#include "core/tests.h" #include "core/defs.h" using namespace dballe; using namespace wreport::tests; using namespace std; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("ident", []() { wassert(actual(Ident()) == Ident()); wassert(actual(Ident("foo")) == Ident("foo")); wassert(actual(Ident().is_missing()).istrue()); wassert(actual(Ident("foo").is_missing()).isfalse()); Ident test; wassert(actual((const char*)test == nullptr).istrue()); test = "antani"; wassert(actual((const char*)test) == "antani"); Ident test1 = test; wassert(actual(test) == Ident("antani")); wassert(actual(test1) == Ident("antani")); test1 = test1; wassert(actual(test) == Ident("antani")); wassert(actual(test1) == Ident("antani")); test1 = Ident("blinda"); wassert(actual(test) == Ident("antani")); wassert(actual(test1) == Ident("blinda")); test = move(test1); wassert(actual(test) == Ident("blinda")); wassert(actual(test1.is_missing()).istrue()); Ident test2(move(test)); wassert(actual(test.is_missing()).istrue()); wassert(actual(test2) == Ident("blinda")); test = string("foo"); wassert(actual(test) == Ident("foo")); wassert(actual(test2) == Ident("blinda")); wassert(actual(Ident("foo") == Ident("foo")).istrue()); wassert(actual(Ident("foo") <= Ident("foo")).istrue()); wassert(actual(Ident("foo") >= Ident("foo")).istrue()); wassert(actual(Ident("foo") == Ident("bar")).isfalse()); wassert(actual(Ident("foo") != Ident("foo")).isfalse()); wassert(actual(Ident("foo") != Ident("bar")).istrue()); wassert(actual(Ident("antani") < Ident("blinda")).istrue()); wassert(actual(Ident("antani") <= Ident("blinda")).istrue()); wassert(actual(Ident("antani") > Ident("blinda")).isfalse()); wassert(actual(Ident("antani") >= Ident("blinda")).isfalse()); wassert(actual(Ident("blinda") < Ident("antani")).isfalse()); wassert(actual(Ident("blinda") <= Ident("antani")).isfalse()); wassert(actual(Ident("blinda") > Ident("antani")).istrue()); wassert(actual(Ident("blinda") >= Ident("antani")).istrue()); }); } } test("core_defs"); } dballe-7.7/dballe/core/matcher.h0000644000175000017500000000465712652630043013517 00000000000000#ifndef DBALLE_CORE_MATCHER_H #define DBALLE_CORE_MATCHER_H #include #include namespace dballe { struct Record; struct Query; namespace matcher { enum Result { MATCH_YES, // Item matches MATCH_NO, // Item does not match MATCH_NA // Match not applicable to this item }; /// Format a Result into a string std::string result_format(Result res); } /** * Common interface for things that are matched. * * This allows the Record-derived matcher to operate on several different * elements. Examples are Record and Msg, but can also be unknown elements * provided by code that uses DB-All.e. */ struct Matched { virtual ~Matched() {} /** * Match variable ID * * This corresponds to B33195 */ virtual matcher::Result match_var_id(int val) const; /** * Match station ID * * This corresponds to DBA_KEY_ANA_ID */ virtual matcher::Result match_station_id(int val) const; /** * Match station WMO code * * If station is -1, only match the block. */ virtual matcher::Result match_station_wmo(int block, int station=-1) const; /// Match datetime virtual matcher::Result match_datetime(const DatetimeRange& range) const; /** * Match coordinates, with bounds in 1/100000 of degree * * Any value can be set to MISSING_INT if not applicable or to represent an * open bound */ virtual matcher::Result match_coords(const LatRange& latrange, const LonRange& lonrange) const; /** * Match rep_memo * * the memo value that is passed is always lowercase */ virtual matcher::Result match_rep_memo(const char* memo) const; /** * Match if min <= val <= max * * It correctly deals with min and max being set to MISSING_INT to signify an open * bound. */ static matcher::Result int_in_range(int val, int min, int max); /** * Match if val is contained inside the given longitude range */ static matcher::Result lon_in_range(int val, int min, int max); }; /** * Match DB-All.e objects using the same queries that can be made on DB-All.e * databases. */ struct Matcher { virtual ~Matcher() {} virtual matcher::Result match(const Matched& item) const = 0; virtual void to_record(dballe::Record& query) const = 0; static std::unique_ptr create(const dballe::Query& query); }; } /* vim:set ts=4 sw=4: */ #endif dballe-7.7/dballe/core/defs.h0000644000175000017500000000411212652630043012777 00000000000000#ifndef DBA_MSG_DEFS_H #define DBA_MSG_DEFS_H /** @file * Common definitions */ #include #include #include #include namespace dballe { /** * A station identifier, that can be any string (including the empty string) or * a missing value. */ class Ident { protected: char* value = nullptr; public: Ident() = default; Ident(const char* value); Ident(const Ident& o); Ident(Ident&& o); ~Ident(); Ident& operator=(const Ident& o); Ident& operator=(Ident&& o); Ident& operator=(const char* o); Ident& operator=(const std::string& o); const char* get() const { return value; } void clear(); int compare(const Ident& o) const; int compare(const char* o) const; int compare(const std::string& o) const; template bool operator==(const T& o) const { return compare(o) == 0; } template bool operator!=(const T& o) const { return compare(o) != 0; } template bool operator<(const T& o) const { return compare(o) < 0; } template bool operator<=(const T& o) const { return compare(o) <= 0; } template bool operator>(const T& o) const { return compare(o) > 0; } template bool operator>=(const T& o) const { return compare(o) >= 0; } bool is_missing() const { return value == nullptr; } operator const char*() const { return value; } operator std::string() const; }; std::ostream& operator<<(std::ostream& out, const Coords& c); std::ostream& operator<<(std::ostream& out, const Date& dt); std::ostream& operator<<(std::ostream& out, const Time& t); std::ostream& operator<<(std::ostream& out, const Datetime& dt); std::ostream& operator<<(std::ostream& out, const DatetimeRange& dtr); std::ostream& operator<<(std::ostream& out, const LatRange& lr); std::ostream& operator<<(std::ostream& out, const LonRange& lr); std::ostream& operator<<(std::ostream& out, const Level& l); std::ostream& operator<<(std::ostream& out, const Trange& l); std::ostream& operator<<(std::ostream& out, const Ident& i); } #endif dballe-7.7/dballe/core/query.h0000644000175000017500000001127712652630043013235 00000000000000#ifndef DBALLE_CORE_QUERY_H #define DBALLE_CORE_QUERY_H #include #include #include #include #include /** * Values for query modifier flags */ /** When values from different reports exist on the same point, only report the * one from the report with the highest priority */ #define DBA_DB_MODIFIER_BEST (1 << 0) /** Do not bother sorting the results */ #define DBA_DB_MODIFIER_UNSORTED (1 << 5) /** Sort by report after ana_id, to ease reconstructing messages on export */ #define DBA_DB_MODIFIER_SORT_FOR_EXPORT (1 << 7) /// Add minimum date, maximum date and data count details to summary query results #define DBA_DB_MODIFIER_SUMMARY_DETAILS (1 << 8) namespace dballe { namespace core { struct JSONWriter; /// Standard dballe::Query implementation struct Query : public dballe::Query { static const uint32_t WANT_MISSING_IDENT = (1 << 0); static const uint32_t WANT_MISSING_LTYPE1 = (1 << 1); static const uint32_t WANT_MISSING_L1 = (1 << 2); static const uint32_t WANT_MISSING_LTYPE2 = (1 << 3); static const uint32_t WANT_MISSING_L2 = (1 << 4); static const uint32_t WANT_MISSING_PIND = (1 << 5); static const uint32_t WANT_MISSING_P1 = (1 << 6); static const uint32_t WANT_MISSING_P2 = (1 << 7); /** * Set a bit a 1 with WANT_MISSING_* constants to specify that the query * wants results in which the corresponding field is set to a missing * value. */ uint32_t want_missing = 0; int ana_id = MISSING_INT; int prio_min = MISSING_INT; int prio_max = MISSING_INT; std::string rep_memo; int mobile = MISSING_INT; Ident ident; LatRange latrange; LonRange lonrange; DatetimeRange datetime; Level level; Trange trange; std::set varcodes; std::string query; std::string ana_filter; std::string data_filter; std::string attr_filter; int limit = MISSING_INT; int block = MISSING_INT; int station = MISSING_INT; std::unique_ptr clone() const override; unsigned get_modifiers() const; DatetimeRange get_datetimerange() const override { return datetime; } void set_datetimerange(const DatetimeRange& dt) override { datetime = dt; } LatRange get_latrange() const override { return latrange; } void set_latrange(const LatRange& lr) override { latrange = lr; } LonRange get_lonrange() const override { return lonrange; } void set_lonrange(const LonRange& lr) override { lonrange = lr; } Level get_level() const override { return level; } void set_level(const Level& level) override { this->level = level; } Trange get_trange() const override { return trange; } void set_trange(const Trange& trange) override { this->trange = trange; } void clear() override; void set_from_record(const dballe::Record& rec) override; /** * Set a record from a ", "-separated string of assignments. * * The implementation is not efficient and the method is not safe for any * input, since ", " could appear in a station identifier. It is however * useful to quickly create test queries for unit testing. */ void set_from_test_string(const std::string& s); /** * Return true if this query matches a subset of the given query. * * In other words, it returns true if this query is the same as \a other, * plus zero or more extra fields set, or zero or more ranges narrowed. */ bool is_subquery(const dballe::Query& other) const override; /** * Generate a sequence of dba_keyword and Var for all contents * of the query that can be represented in a record. */ void foreach_key(std::function dest) const override; /// Print the query contents to stderr void print(FILE* out) const override; /// Send the contents to a JSONWriter void serialize(JSONWriter& out) const; /** * Parse the query=* modifiers specification inside the record, returning the * ORed flags */ static unsigned parse_modifiers(const dballe::Record& rec); /** * Parse the modifiers specification given a query=* string, returning the ORed * flags. */ static unsigned parse_modifiers(const char* str); /** * Return a reference to query downcasted as core::Query. * * Throws an exception if query is not a core::Query. */ static const Query& downcast(const dballe::Query& query); /** * Return a reference to query downcasted as core::Query. * * Throws an exception if query is not a core::Query. */ static Query& downcast(dballe::Query& query); }; } } #endif dballe-7.7/dballe/core/values.cc0000644000175000017500000001117212652630043013517 00000000000000#include "values.h" #include "record.h" using namespace std; using namespace wreport; namespace dballe { void Station::set_from_record(const Record& rec) { if (const Var* var = rec.get("ana_id")) { // If we have ana_id, the rest is optional ana_id = var->enqi(); coords.lat = rec.enq("lat", MISSING_INT); coords.lat = rec.enq("lon", MISSING_INT); ident.clear(); if (const Var* var = rec.get("ident")) ident = var->isset() ? var->enqc() : 0; report = rec.enq("rep_memo", ""); } else { // If we do not have ana_id, we require at least lat, lon and rep_memo ana_id = MISSING_INT; if (const Var* var = rec.get("lat")) coords.lat = var->enqi(); else throw error_notfound("record has no 'lat' set"); if (const Var* var = rec.get("lon")) coords.lon = var->enqi(); else throw error_notfound("record has no 'lon' set"); ident.clear(); if (const Var* var = rec.get("ident")) ident = var->isset() ? var->enqc() : 0; report.clear(); if (const Var* var = rec.get("rep_memo")) { if (var->isset()) report = var->enqs(); else throw error_notfound("record has no 'rep_memo' set"); } } } void Station::print(FILE* out, const char* end) const { if (ana_id == MISSING_INT) fputs("- ", out); else fprintf(out, "%d,", ana_id); if (coords.is_missing()) fputs("(-,-) ", out); else coords.print(out, " "); if (ident.is_missing()) fputs("-", out); else fputs(ident.get(), out); fputs(end, out); } void Sampling::set_from_record(const Record& rec) { Station::set_from_record(rec); const auto& r = core::Record::downcast(rec); datetime = r.get_datetime(); if (datetime.is_missing()) throw error_notfound("record has no date and time information set"); level = r.get_level(); if (level.is_missing()) throw error_notfound("record has no level information set"); trange = r.get_trange(); if (trange.is_missing()) throw error_notfound("record has no time range information set"); } void Sampling::print(FILE* out, const char* end) const { Station::print(out, " "); if (datetime.is_missing()) fputs("xxxx-xx-xx xx:xx:xx ", out); else datetime.print_iso8601(out, ' ', " "); level.print(out, "-", " "); trange.print(out, "-", end); } namespace values { void Value::print(FILE* out) const { if (data_id == MISSING_INT) fputs("-------- ", out); else fprintf(out, "%8d ", data_id); if (!var) fputs("-\n", out); else var->print(out); } } bool Values::operator==(const Values& o) const { auto a = begin(); auto b = o.begin(); while (a != end() && b != o.end()) { if (*a != *b) return false; ++a; ++b; } return a == end() && b == o.end(); } void Values::add_data_id(wreport::Varcode code, int data_id) { auto i = find(code); if (i == end()) return; i->second.data_id = data_id; } void Values::set_from_record(const Record& rec) { const auto& r = core::Record::downcast(rec); for (const auto& i: r.vars()) set(*i); } void Values::set(const wreport::Var& v) { auto i = find(v.code()); if (i == end()) insert(make_pair(v.code(), values::Value(v))); else i->second.set(v); } void Values::set(std::unique_ptr&& v) { auto code = v->code(); auto i = find(code); if (i == end()) insert(make_pair(code, values::Value(move(v)))); else i->second.set(move(v)); } const values::Value& Values::operator[](wreport::Varcode code) const { auto i = find(code); if (i == end()) error_notfound::throwf("variable %01d%02d%03d not found", WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code)); return i->second; } const values::Value* Values::get(wreport::Varcode code) const { auto i = find(code); if (i == end()) return nullptr; return &i->second; } void Values::print(FILE* out) const { for (const auto& i: *this) i.second.print(out); } void StationValues::set_from_record(const Record& rec) { info.set_from_record(rec); values.set_from_record(rec); } void StationValues::print(FILE* out) const { info.print(out); values.print(out); } void DataValues::set_from_record(const Record& rec) { info.set_from_record(rec); values.set_from_record(rec); } void DataValues::print(FILE* out) const { info.print(out); values.print(out); } } dballe-7.7/dballe/core/dump-core-info.cc0000644000175000017500000000331612652630043015045 00000000000000/* * dump-core-info - Dump core information from the library in order to generate documentation * * Copyright (C) 2011 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "record.h" #include "config.h" #include #include #include #include #include using namespace wreport; using namespace dballe; using namespace std; int do_keywords() { using namespace dballe::core; for (int i = 0; i < DBA_KEY_COUNT; ++i) { wreport::Varinfo info = core::Record::keyword_info((dba_keyword)i); printf("%s,%s,%d,%d,%s\n", core::Record::keyword_name((dba_keyword)i), info->unit, info->len, info->scale, info->desc); } return 0; } int main(int argc, const char* argv[]) { string cmd = argv[1]; if (cmd == "keywords") return do_keywords(); else { fprintf(stderr, "Unknown command: %s\n", cmd.c_str()); return 1; } } /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/core/verbose.cc0000644000175000017500000000411112652630043013660 00000000000000/* * DB-ALLe - Archive for punctual meteorological data * * Copyright (C) 2005,2006 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "config.h" #include #include #include #include #ifdef __DATE__ #define DATE __DATE__ #else #define DATE "??? ?? ????" #endif #ifdef __TIME__ #define TIME __TIME__ #else #define TIME "??:??:??" #endif #define out DBA_VERBOSE_STREAM static int level = DBA_VERB_NONE; void dba_verbose_init() { const char* verb = getenv("DBA_VERBOSE"); if (verb != NULL) level = atoi(verb); if (level != DBA_VERB_NONE) { fprintf(out, "%s\n", PACKAGE_NAME " " PACKAGE_VERSION ", compiled on " DATE " " TIME); fprintf(out, "%s", "Copyright (C) 2005-2006 ARPA Emilia Romagna.\n" "DB-ALLe comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it and/or modify it\n" "under the terms of the GNU General Public License as published by the Free\n" "Software Foundation; either version 2 of the License, or (at your option) any\n" "later version.\n"); } } void dba_verbose_set_mask(int mask) { level = mask; } int dba_verbose_is_allowed(int lev) { return (level & lev) != 0; } void dba_verbose(int lev, const char* fmt, ...) { va_list ap; if (!dba_verbose_is_allowed(lev)) return; va_start(ap, fmt); vfprintf(out, fmt, ap); va_end(ap); } dballe-7.7/dballe/core/var-test.cc0000644000175000017500000000160312652630043013763 00000000000000#include "tests.h" #include "var.h" using namespace dballe; using namespace wreport; using namespace wreport::tests; using namespace std; namespace tut { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("single", []() { set codes; resolve_varlist("B12101", codes); wassert(actual(codes.size()) == 1); wassert(actual(*codes.begin()) == WR_VAR(0, 12, 101)); }); add_method("multi", []() { set codes; resolve_varlist("B12101,B12103", codes); wassert(actual(codes.size()) == 2); set::const_iterator i = codes.begin(); wassert(actual(*i) == WR_VAR(0, 12, 101)); ++i; wassert(actual(*i) == WR_VAR(0, 12, 103)); }); } } test("core_var"); } dballe-7.7/dballe/core/stlutils.tcc0000644000175000017500000001510512652630043014267 00000000000000/* * core/stlutils - Useful functions to work with the STL * * Copyright (C) 2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBA_CORE_STLUTILS_TCC #define DBA_CORE_STLUTILS_TCC namespace dballe { namespace stl { namespace stlutils { template struct SequenceSingleton : public Sequence { T val; bool exausted; SequenceSingleton(const T& val) : val(val), exausted(false) {} virtual bool valid() const { return !exausted; } virtual const T& get() const { return val; } virtual void next() { exausted = true; } }; template struct SequenceIters : public Sequence { ITER begin; ITER end; SequenceIters(const ITER& begin, const ITER& end) : begin(begin), end(end) {} virtual bool valid() const { return begin != end; } virtual const typename ITER::value_type& get() const { return *begin; } virtual void next() { ++begin; } }; template struct SequenceUnion : public Sequence { Union sequence_union; typename Union::const_iterator begin; typename Union::const_iterator end; SequenceUnion(std::unique_ptr< Sequences >& sequences) : begin(sequence_union.begin(sequences)), end(sequence_union.end()) {} virtual bool valid() const { return begin != end; } virtual const T& get() const { return *begin; } virtual void next() { ++begin; } }; template struct SequenceIntersection : public Sequence { Intersection sequence_intersection; typename Intersection::const_iterator begin; typename Intersection::const_iterator end; SequenceIntersection(std::unique_ptr< Sequences >& sequences) : begin(sequence_intersection.begin(sequences)), end(sequence_intersection.end()) {} virtual bool valid() const { return begin != end; } virtual const T& get() const { return *begin; } virtual void next() { ++begin; } }; } // back to dballe::stl template void Sequences::add_singleton(const T& val) { this->push_back(new stlutils::SequenceSingleton(val)); } template template void Sequences::add(const ITER& begin, const ITER& end) { this->push_back(new stlutils::SequenceIters(begin, end)); } template template void Sequences::add(const C& container) { this->push_back(new stlutils::SequenceIters(container.begin(), container.end())); } template void Sequences::add(std::unique_ptr< stlutils::Sequence >& sequence) { this->push_back(sequence.release()); } template void Sequences::add_union(std::unique_ptr< Sequences >& sequences) { this->push_back(new stlutils::SequenceUnion(sequences)); } template void Sequences::add_intersection(std::unique_ptr< Sequences >& sequences) { this->push_back(new stlutils::SequenceIntersection(sequences)); } namespace stlutils { template void Itersection::sync_iters() { using namespace std; while (true) { typename Sequences::iterator i = this->sequences->begin(); const T& candidate = (*i)->get(); for ( ; i != this->sequences->end(); ++i) { while ((*i)->valid() && (*i)->get() < candidate) (*i)->next(); // When we reach the end of a sequence, we are done if (!(*i)->valid()) { this->clear(); return; } if ((*i)->get() > candidate) { (*this->sequences)[0]->next(); if (!(*this->sequences)[0]->valid()) { this->clear(); return; } // Continue, but at the while level goto next_round; } } // All sequences have the same item: stop. return; next_round: ; } } template void Iterunion::find_min() { /** * If minval is 0, set it to the minimum value. * If minval points to an element, advance all sequences that have that * element as minimum value, and set minval to the next minimum value. * * Returns false when all sequences are exausted; true if a new minimum * value was found. */ if (minval) { // Advance all sequences that have that element as minimum value, and // set minval to the next minimum value. // Advance all iterators that point to the minimum value for (typename Sequences::iterator i = this->sequences->begin(); i != this->sequences->end(); ++i) { if (!(*i)->valid()) continue; if ((*i)->get() == *minval) (*i)->next(); } } // Set it to the minimum value. bool found = false; minval = 0; for (typename Sequences::const_iterator i = this->sequences->begin(); i != this->sequences->end(); ++i) { if (!(*i)->valid()) continue; if (!minval || (*i)->get() < *minval) { minval = &((*i)->get()); found = true; } } if (!found) { this->clear(); minval = 0; } #if 0 for (typename std::vector< Sequence >::const_iterator i = iters.begin(); i != iters.end(); ) { if (**i != *minval) { ++i; } else { // Same as minval: advance it i->next(); if (i->valid) { ++i; continue; } else if (i == iters.rbegin()) { TODO_reduce_by_one(); break; } else { TODO_swap_last_to_here(); // do not advance i } } } #endif } } } } #endif dballe-7.7/dballe/core/varmatch.cc0000644000175000017500000001373612652630043014035 00000000000000/* * core/varmatch - Variable matcher * * Copyright (C) 2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "varmatch.h" #include "dballe/var.h" #include #include #include using namespace std; using namespace wreport; namespace dballe { Varmatch::Varmatch(wreport::Varcode code) : code(code) {} bool Varmatch::operator()(const wreport::Var& var) const { return var.code() == code; } namespace varmatch { struct BetweenInt : public Varmatch { int min, max; BetweenInt(Varcode code, int min, int max) : Varmatch(code), min(min), max(max) {} bool operator()(const wreport::Var& var) const { if (!Varmatch::operator()(var)) return false; if (!var.isset()) return false; int ival = var.enqi(); return min <= ival && ival <= max; } }; struct BetweenString : public Varmatch { string min, max; BetweenString(Varcode code, const std::string& min, const std::string& max) : Varmatch(code), min(min), max(max) {} bool operator()(const wreport::Var& var) const { if (!Varmatch::operator()(var)) return false; if (!var.isset()) return false; string sval = var.enqs(); return min <= sval && sval <= max; } }; namespace { template static T from_raw_var(const char* val) { throw error_unimplemented("cannot get value for this type"); } template<> int from_raw_var(const char* val) { return strtoul(val, 0, 10); } template<> string from_raw_var(const char* val) { return val; } } template struct Op : public Varmatch { OP op; T val; Op(Varcode code, const T& val) : Varmatch(code), val(val) {} bool operator()(const wreport::Var& var) const { if (!Varmatch::operator()(var)) return false; if (!var.isset()) return false; return op(var.enq(), val); } }; template static unique_ptr make_op(Varcode code, const std::string& op, const T& val) { if (op == "<") return unique_ptr(new Op< T, less >(code, val)); else if (op == "<=") return unique_ptr(new Op< T, less_equal >(code, val)); else if (op == ">") return unique_ptr(new Op< T, greater >(code, val)); else if (op == ">=") return unique_ptr(new Op< T, greater_equal >(code, val)); else if (op == "=" || op == "==") return unique_ptr(new Op< T, equal_to >(code, val)); else if (op == "<>") return unique_ptr(new Op< T, not_equal_to >(code, val)); else error_consistency::throwf("cannot understand comparison operator '%s'", op.c_str()); } } std::unique_ptr Varmatch::parse(const std::string& filter) { size_t sep1_begin = filter.find_first_of("<=>"); if (sep1_begin == string::npos) error_consistency::throwf("cannot find any operator in filter '%s'", filter.c_str()); size_t sep1_end = filter.find_first_not_of("<=>", sep1_begin); if (sep1_end == string::npos) error_consistency::throwf("cannot find end of first operator in filter '%s'", filter.c_str()); size_t sep2_begin = filter.find_first_of("<=>", sep1_end); if (sep2_begin != string::npos) { // min<=B12345<=max size_t sep2_end = filter.find_first_not_of("<=>", sep2_begin); if (sep2_end == string::npos) error_consistency::throwf("cannot find end of second operator in filter '%s'", filter.c_str()); Varcode code = resolve_varcode(filter.substr(sep1_end, sep2_begin - sep1_end).c_str()); Varinfo info = varinfo(code); string min = filter.substr(0, sep1_begin); string max = filter.substr(sep2_end); switch (info->type) { case Vartype::String: return unique_ptr(new varmatch::BetweenString(code, min, max)); case Vartype::Binary: error_consistency::throwf("cannot apply filter '%s' to a binary variable", filter.c_str()); case Vartype::Integer: case Vartype::Decimal: { int imin = info->encode_decimal(strtod(min.c_str(), NULL)); int imax = info->encode_decimal(strtod(max.c_str(), NULL)); return unique_ptr(new varmatch::BetweenInt(code, imin, imax)); } } error_consistency::throwf("unsupported variable type %d", (int)info->type); } else { // B12345<=>val Varcode code = resolve_varcode(filter.substr(0, sep1_begin).c_str()); Varinfo info = varinfo(code); string op = filter.substr(sep1_begin, sep1_end - sep1_begin); switch (info->type) { case Vartype::String: return varmatch::make_op(code, op, filter.substr(sep1_end)); case Vartype::Binary: error_consistency::throwf("cannot apply filter '%s' to a binary variable", filter.c_str()); case Vartype::Integer: case Vartype::Decimal: { int val = info->encode_decimal(strtod(filter.substr(sep1_end).c_str(), NULL)); return varmatch::make_op(code, op, val); } } error_consistency::throwf("unsupported variable type %d", (int)info->type); } } } dballe-7.7/dballe/core/record_keyword.cc0000644000175000017500000003267012652630120015244 00000000000000/* C++ code produced by gperf version 3.0.4 */ /* Command-line: gperf */ /* Computed positions: -k'1-2,$' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif #include #include #include "dballe/var.h" #include "dballe/core/record.h" using namespace wreport; namespace dballe { namespace core { struct tagdef { const char* tag; dba_keyword index; }; #define TOTAL_KEYWORDS 47 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 11 #define MIN_HASH_VALUE 6 #define MAX_HASH_VALUE 90 /* maximum key range = 85, duplicates = 0 */ class RecordKeywords { private: static inline unsigned int hash (const char *str, unsigned int len); public: static struct tagdef *find (const char *str, unsigned int len); }; inline unsigned int RecordKeywords::hash (register const char *str, register unsigned int len) { static unsigned char asso_values[] = { 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 60, 0, 56, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 5, 10, 10, 30, 0, 0, 91, 40, 10, 25, 91, 20, 0, 5, 35, 0, 0, 5, 10, 20, 40, 20, 91, 0, 0, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91 }; return len + asso_values[(unsigned char)str[1]+1] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]]; } static struct tagdef wordlist[] = { {""}, {""}, {""}, {""}, {""}, {""}, {"mobile", DBA_KEY_MOBILE}, {"yearmax", DBA_KEY_YEARMAX}, {"monthmax", DBA_KEY_MONTHMAX}, {"year", DBA_KEY_YEAR}, {""}, {""}, {"yearmin", DBA_KEY_YEARMIN}, {"monthmin", DBA_KEY_MONTHMIN}, {""}, {""}, {"secmax", DBA_KEY_SECMAX}, {"priomax", DBA_KEY_PRIOMAX}, {"priority", DBA_KEY_PRIORITY}, {""}, {""}, {"secmin", DBA_KEY_SECMIN}, {"priomin", DBA_KEY_PRIOMIN}, {"sec", DBA_KEY_SEC}, {""}, {"query", DBA_KEY_QUERY}, {"lonmax", DBA_KEY_LONMAX}, {""}, {"lon", DBA_KEY_LON}, {""}, {"leveltype2", DBA_KEY_LEVELTYPE2}, {"lonmin", DBA_KEY_LONMIN}, {"minumax", DBA_KEY_MINUMAX}, {"min", DBA_KEY_MIN}, {""}, {"ident", DBA_KEY_IDENT}, {"latmax", DBA_KEY_LATMAX}, {"minumin", DBA_KEY_MINUMIN}, {"var", DBA_KEY_VAR}, {""}, {"pindicator", DBA_KEY_PINDICATOR}, {"latmin", DBA_KEY_LATMIN}, {""}, {"day", DBA_KEY_DAY}, {""}, {"month", DBA_KEY_MONTH}, {"daymax", DBA_KEY_DAYMAX}, {"hourmax", DBA_KEY_HOURMAX}, {"rep_memo", DBA_KEY_REP_MEMO}, {"hour", DBA_KEY_HOUR}, {"context_id", DBA_KEY_CONTEXT_ID}, {"daymin", DBA_KEY_DAYMIN}, {"hourmin", DBA_KEY_HOURMIN}, {"lat", DBA_KEY_LAT}, {""}, {"ana_filter", DBA_KEY_ANA_FILTER}, {"data_filter", DBA_KEY_DATA_FILTER}, {"varlist", DBA_KEY_VARLIST}, {"p2", DBA_KEY_P2}, {""}, {""}, {"attr_filter", DBA_KEY_ATTR_FILTER}, {"p1", DBA_KEY_P1}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"limit", DBA_KEY_LIMIT}, {"var_related", DBA_KEY_VAR_RELATED}, {""}, {""}, {""}, {""}, {"ana_id", DBA_KEY_ANA_ID}, {""}, {"l2", DBA_KEY_L2}, {""}, {""}, {""}, {"l1", DBA_KEY_L1}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"leveltype1", DBA_KEY_LEVELTYPE1} }; struct tagdef * RecordKeywords::find (register const char *str, register unsigned int len) { if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len); if (key <= MAX_HASH_VALUE && key >= 0) { register const char *s = wordlist[key].tag; if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') return &wordlist[key]; } } return 0; } #define DEF_MAXINT 0, 10, 0, 31 #define DEF_INT(digits) 0, digits, 0, digits*8 namespace { struct keyword_infos { struct _Varinfo infos[DBA_KEY_COUNT]; keyword_infos() { infos[DBA_KEY_PRIORITY ].set_bufr (0, "Priority of this type of report", "NUMBER", DEF_MAXINT); infos[DBA_KEY_PRIOMAX ].set_bufr (0, "Maximum priority of reports queried", "NUMBER", DEF_MAXINT); infos[DBA_KEY_PRIOMIN ].set_bufr (0, "Minimum priority of reports queried", "NUMBER", DEF_MAXINT); infos[DBA_KEY_REP_MEMO ].set_string(0, "Mnemonic alias for type of report", 20); infos[DBA_KEY_ANA_ID ].set_bufr (0, "Station database ID", "NUMERIC", DEF_MAXINT); infos[DBA_KEY_MOBILE ].set_bufr (0, "Station is mobile", "NUMERIC", DEF_MAXINT); infos[DBA_KEY_IDENT ].set_string(0, "Identifier of flight or ship", 64); infos[DBA_KEY_LAT ].set_bufr (0, "Latitude", "DEGREE", 5, 7, -9000000, 25); infos[DBA_KEY_LON ].set_bufr (0, "Longitude", "DEGREE", 5, 8, -18000000, 26); infos[DBA_KEY_LATMAX ].set_bufr (0, "Maximum latitude queried", "DEGREE", 5, 7, -9000000, 25); infos[DBA_KEY_LATMIN ].set_bufr (0, "Minimum latitude queried", "DEGREE", 5, 7, -9000000, 25); infos[DBA_KEY_LONMAX ].set_bufr (0, "Maximum longitude queried", "DEGREE", 5, 8, -18000000, 26); infos[DBA_KEY_LONMIN ].set_bufr (0, "Minimum longitude queried", "DEGREE", 5, 8, -18000000, 26); infos[DBA_KEY_YEAR ].set_bufr (0, "Year", "YEAR", DEF_INT(4)); infos[DBA_KEY_MONTH ].set_bufr (0, "Month", "MONTH", DEF_INT(2)); infos[DBA_KEY_DAY ].set_bufr (0, "Day", "DAY", DEF_INT(2)); infos[DBA_KEY_HOUR ].set_bufr (0, "Hour", "HOUR", DEF_INT(2)); infos[DBA_KEY_MIN ].set_bufr (0, "Minutes", "MINUTE", DEF_INT(2)); infos[DBA_KEY_SEC ].set_bufr (0, "Seconds", "SECOND", DEF_INT(2)); infos[DBA_KEY_YEARMAX ].set_bufr (0, "Maximum year queried", "YEAR", DEF_INT(4)); infos[DBA_KEY_YEARMIN ].set_bufr (0, "Year or minimum year queried", "YEAR", DEF_INT(4)); infos[DBA_KEY_MONTHMAX ].set_bufr (0, "Maximum month queried", "MONTH", DEF_INT(2)); infos[DBA_KEY_MONTHMIN ].set_bufr (0, "Minimum month queried", "MONTH", DEF_INT(2)); infos[DBA_KEY_DAYMAX ].set_bufr (0, "Maximum day queried", "DAY", DEF_INT(2)); infos[DBA_KEY_DAYMIN ].set_bufr (0, "Minimum day queried", "DAY", DEF_INT(2)); infos[DBA_KEY_HOURMAX ].set_bufr (0, "Maximum hour queried", "HOUR", DEF_INT(2)); infos[DBA_KEY_HOURMIN ].set_bufr (0, "Minumum hour queried", "HOUR", DEF_INT(2)); infos[DBA_KEY_MINUMAX ].set_bufr (0, "Maxminum minutes queried", "MINUTE", DEF_INT(2)); infos[DBA_KEY_MINUMIN ].set_bufr (0, "Minimum minutes queried", "MINUTE", DEF_INT(2)); infos[DBA_KEY_SECMAX ].set_bufr (0, "Maxminum seconds queried", "SECOND", DEF_INT(2)); infos[DBA_KEY_SECMIN ].set_bufr (0, "Minimum seconds queried", "SECOND", DEF_INT(2)); infos[DBA_KEY_LEVELTYPE1 ].set_bufr (0, "Type of first level", "NUMBER", DEF_MAXINT); infos[DBA_KEY_L1 ].set_bufr (0, "Level layer L1", "NUMBER", DEF_MAXINT); infos[DBA_KEY_LEVELTYPE2 ].set_bufr (0, "Type of second level", "NUMBER", DEF_MAXINT); infos[DBA_KEY_L2 ].set_bufr (0, "Level layer L2", "NUMBER", DEF_MAXINT); infos[DBA_KEY_PINDICATOR ].set_bufr (0, "P indicator for time range", "NUMBER", DEF_MAXINT); infos[DBA_KEY_P1 ].set_bufr (0, "Time range P1", "SECOND", DEF_MAXINT); infos[DBA_KEY_P2 ].set_bufr (0, "Time range P2", "SECOND", DEF_MAXINT); infos[DBA_KEY_VAR ].set_string(0, "Variable queried", 7); infos[DBA_KEY_VARLIST ].set_string(0, "List of variables to query", 255); infos[DBA_KEY_CONTEXT_ID ].set_bufr (0, "Context ID of the variable", "NUMERIC", DEF_MAXINT); infos[DBA_KEY_QUERY ].set_string(0, "Query behaviour modifier", 255); infos[DBA_KEY_ANA_FILTER ].set_string(0, "Filter on anagraphical data", 255); infos[DBA_KEY_DATA_FILTER].set_string(0, "Filter on data", 255); infos[DBA_KEY_ATTR_FILTER].set_string(0, "Filter on data attributes", 255); infos[DBA_KEY_LIMIT ].set_bufr (0, "Maximum number of results to return", "NUMBER", DEF_MAXINT); infos[DBA_KEY_VAR_RELATED].set_string(0, "Variable related to attribute queried", 6); } }; static struct keyword_infos* infos = NULL; } static const char* keyword_names[] = { "priority", "priomax", "priomin", "rep_memo", "ana_id", "mobile", "ident", "lat", "lon", "latmax", "latmin", "lonmax", "lonmin", "year", "month", "day", "hour", "min", "sec", "yearmax", "yearmin", "monthmax", "monthmin", "daymax", "daymin", "hourmax", "hourmin", "minumax", "minumin", "secmax", "secmin", "leveltype1", "l1", "leveltype2", "l2", "pindicator", "p1", "p2", "var", "varlist", "context_id", "query", "ana_filter", "data_filter", "attr_filter", "limit", "var_related", }; const char* Record::keyword_name(dba_keyword key) { return keyword_names[key]; } Varinfo Record::keyword_info(dba_keyword keyword) { if (infos == NULL) infos = new keyword_infos; return &(infos->infos[keyword]); } dba_keyword Record::keyword_byname(const char* tag) { struct tagdef* res = RecordKeywords::find(tag, strlen(tag)); if (res == NULL) return DBA_KEY_ERROR; else return res->index; } dba_keyword Record::keyword_byname_len(const char* tag, int len) { struct tagdef* res = RecordKeywords::find(tag, len); if (res == NULL) return DBA_KEY_ERROR; else return res->index; } /* dba_err dba_record_keyword_selftest() { dba_keyword i, j; for (i = 0; i < DBA_KEY_COUNT; i++) { if (wordlist[i + 1].index != i) return dba_error_consistency("wordlist entry %d has index %d that does not match the position", i, wordlist[i + 1].index); j = dba_record_keyword_byname(wordlist[i + 1].tag); if (j != i) return dba_error_consistency("hashing of entry '%s' did not give expected index %d", wordlist[i + 1].tag, i); } return dba_error_ok(); } */ } } dballe-7.7/dballe/core/json-test.cc0000644000175000017500000000550312652630043014147 00000000000000#include "tests.h" #include "json.h" #include using namespace std; using namespace dballe; using namespace dballe::tests; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("null", []() { // null value stringstream out; core::JSONWriter writer(out); writer.add_null(); wassert(actual(out.str()) == "null"); }); add_method("bool", []() { // bool value stringstream out; core::JSONWriter writer(out); writer.add(true); wassert(actual(out.str()) == "true"); out.str(""); writer.add(false); wassert(actual(out.str()) == "false"); }); add_method("int", []() { // int value stringstream out; core::JSONWriter writer(out); writer.add(1); wassert(actual(out.str()) == "1"); out.str(""); writer.add(-1234567); wassert(actual(out.str()) == "-1234567"); }); add_method("double", []() { // double value stringstream out; core::JSONWriter writer(out); writer.add(1.1); wassert(actual(out.str()) == "1.100000"); out.str(""); writer.add(-1.1); wassert(actual(out.str()) == "-1.100000"); out.str(""); writer.add(1.0); wassert(actual(out.str()) == "1.0"); out.str(""); writer.add(-1.0); wassert(actual(out.str()) == "-1.0"); }); add_method("string", []() { // string value stringstream out; core::JSONWriter writer(out); writer.add(""); wassert(actual(out.str()) == "\"\""); out.str(""); writer.add("antani"); wassert(actual(out.str()) == "\"antani\""); out.str(""); writer.add("\n"); wassert(actual(out.str()) == "\"\\n\""); }); add_method("list", []() { // list value stringstream out; core::JSONWriter writer(out); writer.start_list(); writer.add(""); writer.add(1); writer.add(1.0); writer.end_list(); wassert(actual(out.str()) == "[\"\",1,1.0]"); }); add_method("mapping", []() { // mapping value stringstream out; core::JSONWriter writer(out); writer.start_mapping(); writer.add("", 1); writer.add("antani", 1.0); writer.end_mapping(); wassert(actual(out.str()) == "{\"\":1,\"antani\":1.0}"); }); }; } test("core_json"); } dballe-7.7/dballe/core/arrayfile.h0000644000175000017500000000116012652630043014034 00000000000000#ifndef DBALLE_CORE_ARRAYFILE_H #define DBALLE_CORE_ARRAYFILE_H /** @file * @ingroup core * In-memory versions of File, to be used for testing, */ #include #include namespace dballe { namespace core { class ArrayFile : public dballe::core::File { protected: Encoding file_type; public: std::vector msgs; /// Current reading offset in msgs unsigned current; ArrayFile(Encoding type); virtual ~ArrayFile(); Encoding encoding() const override; BinaryMessage read() override; void write(const std::string& msg) override; }; } } #endif dballe-7.7/dballe/core/record.cc0000644000175000017500000006544712652630043013514 00000000000000#include "record.h" #include "var.h" #include "aliases.h" #include "defs.h" #include "config.h" #include #include #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace core { /* * Size of the keyword table. It should be the number of items in * dba_record_keyword.gperf, plus 1 */ #define KEYWORD_TABLE_SIZE DBA_KEY_COUNT #define assert_is_dba_record(rec) do { \ assert((rec) != NULL); \ } while (0) std::ostream& operator<<(std::ostream& o, dba_keyword k) { return o << Record::keyword_name(k); } Record::Record() { memset(keydata, 0, sizeof(keydata)); } Record::Record(const Record& rec) { // Copy the keyword table for (int i = 0; i < KEYWORD_TABLE_SIZE; ++i) { if (rec.keydata[i] == NULL) keydata[i] = NULL; else keydata[i] = new Var(*rec.keydata[i]); } // Copy the variable list for (vector::const_iterator i = rec.m_vars.begin(); i != rec.m_vars.end(); ++i) m_vars.push_back(new Var(**i)); } Record::~Record() { clear(); } unique_ptr Record::clone() const { return unique_ptr(new Record(*this)); } const Record& Record::downcast(const dballe::Record& record) { const Record* ptr = dynamic_cast(&record); if (!ptr) throw error_consistency("record given is not a core::Record"); return *ptr; } Record& Record::downcast(dballe::Record& record) { Record* ptr = dynamic_cast(&record); if (!ptr) throw error_consistency("record given is not a core::Record"); return *ptr; } wreport::Var& Record::obtain(const char* name) { Varcode code = 0; if (name[0] != 'B' && (code = varcode_alias_resolve(name)) == 0) { dba_keyword param = keyword_byname(name); if (param == DBA_KEY_ERROR) error_notfound::throwf("invalid parameter \"%s\"", name); return obtain(param); } else { if (code == 0) code = WR_STRING_TO_VAR(name + 1); return obtain(code); } } wreport::Var& Record::obtain(dba_keyword key) { if (keydata[key] == NULL) keydata[key] = new Var(keyword_info(key)); return *keydata[key]; } wreport::Var& Record::obtain(wreport::Varcode key) { int pos = find_item(key); if (pos == -1) { // Insertion sort the new variable // Enlarge the buffer m_vars.resize(m_vars.size() + 1); /* Insertionsort. Crude, but our datasets should be too small for an * RB-Tree to be worth it */ for (pos = m_vars.size() - 1; pos > 0; --pos) if (m_vars[pos - 1]->code() > key) m_vars[pos] = m_vars[pos - 1]; else break; m_vars[pos] = newvar(key).release(); } return *m_vars[pos]; } void Record::seti(const char* key, int val) { if (val == MISSING_INT) unset(key); else obtain(key).seti(val); } void Record::setd(const char* key, double val) { obtain(key).setd(val); } void Record::setc(const char* key, const char* val) { if (!val) unset(key); else { obtain(key).setc(val); } } void Record::sets(const char* key, const std::string& val) { obtain(key).setc(val.c_str()); } void Record::setf(const char* key, const char* val) { // See https://github.com/ARPA-SIMC/dballe/issues/29 auto& var = obtain(key); switch (var.info()->type) { case Vartype::String: case Vartype::Binary: var.setf(val); break; case Vartype::Decimal: case Vartype::Integer: if (strcmp(val, "-") == 0) unset(key); else var.setf(val); break; } } void Record::set_datetime(const Datetime& dt) { if (dt.is_missing()) { key_unset(DBA_KEY_YEAR); key_unset(DBA_KEY_MONTH); key_unset(DBA_KEY_DAY); key_unset(DBA_KEY_HOUR); key_unset(DBA_KEY_MIN); key_unset(DBA_KEY_SEC); } else { seti("year", (int)dt.year); seti("month", (int)dt.month); seti("day", (int)dt.day); seti("hour", (int)dt.hour); seti("min", (int)dt.minute); seti("sec", (int)dt.second); } key_unset(DBA_KEY_YEARMIN); key_unset(DBA_KEY_MONTHMIN); key_unset(DBA_KEY_DAYMIN); key_unset(DBA_KEY_HOURMIN); key_unset(DBA_KEY_MINUMIN); key_unset(DBA_KEY_SECMIN); key_unset(DBA_KEY_YEARMAX); key_unset(DBA_KEY_MONTHMAX); key_unset(DBA_KEY_DAYMAX); key_unset(DBA_KEY_HOURMAX); key_unset(DBA_KEY_MINUMAX); key_unset(DBA_KEY_SECMAX); } void Record::set_datetimerange(const DatetimeRange& range) { if (range.is_missing()) { key_unset(DBA_KEY_YEAR); key_unset(DBA_KEY_MONTH); key_unset(DBA_KEY_DAY); key_unset(DBA_KEY_HOUR); key_unset(DBA_KEY_MIN); key_unset(DBA_KEY_SEC); key_unset(DBA_KEY_YEARMIN); key_unset(DBA_KEY_MONTHMIN); key_unset(DBA_KEY_DAYMIN); key_unset(DBA_KEY_HOURMIN); key_unset(DBA_KEY_MINUMIN); key_unset(DBA_KEY_SECMIN); key_unset(DBA_KEY_YEARMAX); key_unset(DBA_KEY_MONTHMAX); key_unset(DBA_KEY_DAYMAX); key_unset(DBA_KEY_HOURMAX); key_unset(DBA_KEY_MINUMAX); key_unset(DBA_KEY_SECMAX); } else if (range.min == range.max) { set(range.min); } else if (range.min.is_missing()) { key_unset(DBA_KEY_YEAR); key_unset(DBA_KEY_MONTH); key_unset(DBA_KEY_DAY); key_unset(DBA_KEY_HOUR); key_unset(DBA_KEY_MIN); key_unset(DBA_KEY_SEC); key_unset(DBA_KEY_YEARMIN); key_unset(DBA_KEY_MONTHMIN); key_unset(DBA_KEY_DAYMIN); key_unset(DBA_KEY_HOURMIN); key_unset(DBA_KEY_MINUMIN); key_unset(DBA_KEY_SECMIN); seti("yearmax", range.max.year); seti("monthmax", range.max.month); seti("daymax", range.max.day); seti("hourmax", range.max.hour); seti("minumax", range.max.minute); seti("secmax", range.max.second); } else if (range.max.is_missing()) { key_unset(DBA_KEY_YEAR); key_unset(DBA_KEY_MONTH); key_unset(DBA_KEY_DAY); key_unset(DBA_KEY_HOUR); key_unset(DBA_KEY_MIN); key_unset(DBA_KEY_SEC); seti("yearmin", range.min.year); seti("monthmin", range.min.month); seti("daymin", range.min.day); seti("hourmin", range.min.hour); seti("minumin", range.min.minute); seti("secmin", range.min.second); key_unset(DBA_KEY_YEARMAX); key_unset(DBA_KEY_MONTHMAX); key_unset(DBA_KEY_DAYMAX); key_unset(DBA_KEY_HOURMAX); key_unset(DBA_KEY_MINUMAX); key_unset(DBA_KEY_SECMAX); } else { if (range.min.year == range.max.year) { seti("year", range.min.year); key_unset(DBA_KEY_YEARMIN); key_unset(DBA_KEY_YEARMAX); } else { key_unset(DBA_KEY_YEAR); seti("yearmin", range.min.year); seti("yearmax", range.max.year); } if (range.min.month == range.max.month) { seti("month", range.min.month); key_unset(DBA_KEY_MONTHMIN); key_unset(DBA_KEY_MONTHMAX); } else { key_unset(DBA_KEY_MONTH); seti("monthmin", range.min.month); seti("monthmax", range.max.month); } if (range.min.day == range.max.day) { seti("day", range.min.day); key_unset(DBA_KEY_DAYMIN); key_unset(DBA_KEY_DAYMAX); } else { key_unset(DBA_KEY_DAY); seti("daymin", range.min.day); seti("daymax", range.max.day); } if (range.min.hour == range.max.hour) { seti("hour", range.min.hour); key_unset(DBA_KEY_HOURMIN); key_unset(DBA_KEY_HOURMAX); } else { key_unset(DBA_KEY_HOUR); seti("hourmin", range.min.hour); seti("hourmax", range.max.hour); } if (range.min.minute == range.max.minute) { seti("min", range.min.minute); key_unset(DBA_KEY_MINUMIN); key_unset(DBA_KEY_MINUMAX); } else { key_unset(DBA_KEY_MIN); seti("minumin", range.min.minute); seti("minumax", range.max.minute); } if (range.min.second == range.max.second) { seti("sec", range.min.second); key_unset(DBA_KEY_SECMIN); key_unset(DBA_KEY_SECMAX); } else { key_unset(DBA_KEY_SEC); seti("secmin", range.min.second); seti("secmax", range.max.second); } } } void Record::set_level(const Level& lev) { if (lev.ltype1 == MISSING_INT) unset("leveltype1"); else seti("leveltype1", lev.ltype1); if (lev.l1 == MISSING_INT) unset("l1"); else seti("l1", lev.l1); if (lev.ltype2 == MISSING_INT) unset("leveltype2"); else seti("leveltype2", lev.ltype2); if (lev.l2 == MISSING_INT) unset("l2"); else seti("l2", lev.l2); } void Record::set_trange(const Trange& tr) { if (tr.pind == MISSING_INT) unset("pindicator"); else seti("pindicator", tr.pind); if (tr.p1 == MISSING_INT) unset("p1"); else seti("p1", tr.p1); if (tr.p2 == MISSING_INT) unset("p2"); else seti("p2", tr.p2); } void Record::set_var(const wreport::Var& var) { if (var.isset()) obtain(var.code()).setval(var); else var_unset(var.code()); } void Record::set_var_acquire(std::unique_ptr&& var) { int pos = find_item(var->code()); if (pos == -1) { // Insertion sort the new variable // Enlarge the buffer m_vars.resize(m_vars.size() + 1); /* Insertionsort. Crude, but our datasets should be too small for an * RB-Tree to be worth it */ for (pos = m_vars.size() - 1; pos > 0; --pos) if (m_vars[pos - 1]->code() > var->code()) m_vars[pos] = m_vars[pos - 1]; else break; } else delete m_vars[pos]; m_vars[pos] = var.release(); } void Record::set_latrange(const LatRange& lr) { if (lr.is_missing()) { unset("lat"); unset("latmin"); unset("latmax"); } else if (lr.imin == lr.imax) { seti("lat", lr.imin); unset("latmin"); unset("latmax"); } else { unset("lat"); seti("latmin", lr.imin); seti("latmax", lr.imax); } } void Record::set_lonrange(const LonRange& lr) { if (lr.is_missing()) { unset("lon"); unset("lonmin"); unset("lonmax"); } else if (lr.imin == lr.imax) { seti("lon", lr.imin); unset("lonmin"); unset("lonmax"); } else { unset("lon"); seti("lonmin", lr.imin); seti("lonmax", lr.imax); } } const wreport::Var* Record::get(const char* key) const { Varcode code = 0; if (key[0] != 'B' && (code = varcode_alias_resolve(key)) == 0) { dba_keyword param = keyword_byname(key); if (param == DBA_KEY_ERROR) error_notfound::throwf("invalid parameter \"%s\"", key); return key_peek(param); } else { if (code == 0) code = WR_STRING_TO_VAR(key + 1); return var_peek(code); } } Record& Record::operator=(const Record& rec) { // Prevent self-copying if (this == &rec) return *this; // Copy the keyword table first for (int i = 0; i < KEYWORD_TABLE_SIZE; i++) { if (keydata[i] != NULL) { if (rec.keydata[i] != NULL) *keydata[i] = *rec.keydata[i]; else { delete keydata[i]; keydata[i] = NULL; } } else if (rec.keydata[i] != NULL) keydata[i] = new Var(*rec.keydata[i]); } // Copy the variable list clear_vars(); for (vector::const_iterator i = rec.m_vars.begin(); i != rec.m_vars.end(); ++i) m_vars.push_back(new Var(**i)); return *this; } bool Record::equals(const dballe::Record& other) const { const auto& rec = downcast(other); // Compare the keywords for (int i = 0; i < KEYWORD_TABLE_SIZE; i++) { if (keydata[i] == NULL && rec.keydata[i] == NULL) continue; if (keydata[i] == NULL || rec.keydata[i] == NULL) return false; if (*keydata[i] != *rec.keydata[i]) return false; } // Compare the variables vector::const_iterator i1 = m_vars.begin(); vector::const_iterator i2 = rec.m_vars.begin(); for ( ; i1 != m_vars.end() && i2 != rec.m_vars.end(); ++i1, ++i2) if (**i1 != **i2) return false; if (i1 != m_vars.end() || i2 != rec.m_vars.end()) return false; return true; } void Record::clear_vars() { for (vector::iterator i = m_vars.begin(); i != m_vars.end(); ++i) delete *i; m_vars.clear(); } void Record::clear() { for (int i = 0; i < KEYWORD_TABLE_SIZE; ++i) if (keydata[i] != NULL) { delete keydata[i]; keydata[i] = NULL; } clear_vars(); } int Record::find_item(Varcode code) const throw () { /* Binary search */ int low = 0, high = m_vars.size() - 1; while (low <= high) { int middle = low + (high - low)/2; int cmp = (int)code - (int)m_vars[middle]->code(); if (cmp < 0) high = middle - 1; else if (cmp > 0) low = middle + 1; else return middle; } return -1; } Var& Record::get_item(Varcode code) { int pos = find_item(code); if (pos == -1) error_notfound::throwf("looking for parameter \"B%02d%03d\"", WR_VAR_X(code), WR_VAR_Y(code)); return *m_vars[pos]; } const Var& Record::get_item(Varcode code) const { int pos = find_item(code); if (pos == -1) error_notfound::throwf("looking for parameter \"B%02d%03d\"", WR_VAR_X(code), WR_VAR_Y(code)); return *m_vars[pos]; } void Record::remove_item(Varcode code) { int pos = find_item(code); if (pos == -1) return; delete m_vars[pos]; m_vars.erase(m_vars.begin() + pos); } void Record::add(const dballe::Record& rec) { const auto& source = downcast(rec); // Add the keyword table for (int i = 0; i < KEYWORD_TABLE_SIZE; i++) { if (source.keydata[i] != NULL) { if (keydata[i] != NULL) *keydata[i] = *source.keydata[i]; else keydata[i] = new Var(*source.keydata[i]); } } // Add the variables list vector::const_iterator src = source.m_vars.begin(); size_t dst = 0; while (src != source.m_vars.end() && dst < m_vars.size()) { if ((*src)->code() < m_vars[dst]->code()) { // Insert m_vars.insert(m_vars.begin() + dst, new Var(**src)); ++src; } else if ((*src)->code() == m_vars[dst]->code()) { // Overwrite *m_vars[dst] = **src; ++dst; ++src; } else { ++dst; } } // Append the remaining source vars for ( ; src != source.m_vars.end(); ++src) m_vars.push_back(new Var(**src)); } void Record::set_to_difference(const Record& source1, const Record& source2) { // Copy the keyword table for (unsigned i = 0; i < KEYWORD_TABLE_SIZE; ++i) { if (!source2.keydata[i]) { // Has been deleted: skip delete keydata[i]; keydata[i] = nullptr; } else if (!source1.keydata[i]) { // Has been added in source2: add *keydata[i] = *source2.keydata[i]; } else if (source1.keydata[i] != source2.keydata[i]) { // Has been changed in source2: add *keydata[i] = *source2.keydata[i]; } else { // Has not been changed: skip delete keydata[i]; keydata[i] = nullptr; } } // Copy the variables list clear_vars(); vector::const_iterator s1 = source1.m_vars.begin(); vector::const_iterator s2 = source2.m_vars.begin(); while (s1 != source1.m_vars.end() && s2 != source2.m_vars.end()) { if ((*s1)->code() < (*s2)->code()) ++s1; else if ((*s1)->code() == (*s2)->code()) { if (**s1 != **s2) m_vars.push_back(new Var(**s2)); ++s1; ++s2; } else if ((*s2)->code() < (*s1)->code()) { m_vars.push_back(new Var(**s2)); ++s2; } } for ( ; s2 != source2.m_vars.end(); ++s2) m_vars.push_back(new Var(**s2)); } bool Record::contains(const dballe::Record& rec) const { const auto& subset = downcast(rec); // Compare the keyword tables for (int i = 0; i < KEYWORD_TABLE_SIZE; ++i) { if (subset.keydata[i] != NULL && keydata[i] == NULL) return false; if (subset.keydata[i] != NULL && keydata[i] != NULL && *subset.keydata[i] != *keydata[i]) return false; } // Compare the values vector::const_iterator s1 = m_vars.begin(); vector::const_iterator s2 = subset.m_vars.begin(); while (s1 != m_vars.end() && s2 != subset.m_vars.end()) { if ((*s1)->code() < (*s2)->code()) // s1 has a value not in s2 ++s1; else if ((*s1)->code() == (*s2)->code()) { // they both have the same values if (**s1 != **s2) return false; ++s1; ++s2; } else if ((*s2)->code() < (*s1)->code()) { // s2 has a value not in s1 return false; } } return true; } const Var* Record::key_peek(dba_keyword parameter) const throw () { return keydata[parameter]; } const Var* Record::var_peek(Varcode code) const throw () { int pos = find_item(code); if (pos == -1) return NULL; return m_vars[pos]; } void Record::key_unset(dba_keyword parameter) { if (keydata[parameter] != NULL) { delete keydata[parameter]; keydata[parameter] = NULL; } } void Record::var_unset(wreport::Varcode code) { int pos = find_item(code); if (pos != -1) { delete m_vars[pos]; m_vars.erase(m_vars.begin() + pos); } } void Record::unset(const char* name) { Varcode code = 0; if (name[0] != 'B' && (code = varcode_alias_resolve(name)) == 0) { dba_keyword param = keyword_byname(name); if (param == DBA_KEY_ERROR) error_notfound::throwf("invalid parameter \"%s\"", name); return key_unset(param); } else { if (code == 0) code = WR_STRING_TO_VAR(name + 1); return var_unset(code); } } void Record::foreach_key_ref(std::function dest) const { // Generate keys for (unsigned i = 0; i < KEYWORD_TABLE_SIZE; ++i) { if (keydata[i] == NULL) continue; if (!keydata[i]->isset()) continue; dest(keyword_name((dba_keyword)i), *keydata[i]); } // Generate variables string varcode; for (const auto& i: m_vars) { varcode = varcode_format(i->code()); dest(varcode.c_str(), *i); } } void Record::foreach_key_copy(std::function&&)> dest) const { // Generate keys for (unsigned i = 0; i < KEYWORD_TABLE_SIZE; ++i) { if (keydata[i] == NULL) continue; if (!keydata[i]->isset()) continue; dest(keyword_name((dba_keyword)i), move(newvar(*keydata[i]))); } // Generate variables string varcode; for (const auto& i: m_vars) { varcode = varcode_format(i->code()); dest(varcode.c_str(), move(newvar(*i))); } } bool Record::iter_keys(std::function f) const { for (unsigned i = 0; i < KEYWORD_TABLE_SIZE; ++i) { if (keydata[i] == NULL) continue; if (!f((dba_keyword)i, *keydata[i])) return false; } return true; } const std::vector& Record::vars() const { return m_vars; } Level Record::get_level() const { return Level( enq("leveltype1", MISSING_INT), enq("l1", MISSING_INT), enq("leveltype2", MISSING_INT), enq("l2", MISSING_INT)); } Trange Record::get_trange() const { return Trange( enq("pindicator", MISSING_INT), enq("p1", MISSING_INT), enq("p2", MISSING_INT)); } Datetime Record::get_datetime() const { if (const Var* var = key_peek(DBA_KEY_YEAR)) return Datetime::lower_bound( var->enqi(), enq("month", MISSING_INT), enq("day", MISSING_INT), enq("hour", MISSING_INT), enq("min", MISSING_INT), enq("sec", MISSING_INT)); else return Datetime(); } DatetimeRange Record::get_datetimerange() const { // fetch all values involved in the computation int ye = enq("year", MISSING_INT); int mo = enq("month", MISSING_INT); int da = enq("day", MISSING_INT); int ho = enq("hour", MISSING_INT); int mi = enq("min", MISSING_INT); int se = enq("sec", MISSING_INT); int yemin = enq("yearmin", MISSING_INT); int momin = enq("monthmin", MISSING_INT); int damin = enq("daymin", MISSING_INT); int homin = enq("hourmin", MISSING_INT); int mimin = enq("minumin", MISSING_INT); int semin = enq("secmin", MISSING_INT); int yemax = enq("yearmax", MISSING_INT); int momax = enq("monthmax", MISSING_INT); int damax = enq("daymax", MISSING_INT); int homax = enq("hourmax", MISSING_INT); int mimax = enq("minumax", MISSING_INT); int semax = enq("secmax", MISSING_INT); // give absolute values priority over ranges if (ye != MISSING_INT) yemin = yemax = ye; if (mo != MISSING_INT) momin = momax = mo; if (da != MISSING_INT) damin = damax = da; if (ho != MISSING_INT) homin = homax = ho; if (mi != MISSING_INT) mimin = mimax = mi; if (se != MISSING_INT) semin = semax = se; return DatetimeRange(yemin, momin, damin, homin, mimin, semin, yemax, momax, damax, homax, mimax, semax); } void Record::set_coords(const Coords& c) { seti("lat", c.lat); seti("lon", c.lon); } void Record::set_from_string(const char* str) { // Split the input as name=val const char* s = strchr(str, '='); if (!s) error_consistency::throwf("there should be an = between the name and the value in '%s'", str); string key(str, s - str); setf(key.c_str(), s + 1); } void Record::set_from_test_string(const std::string& s) { if (s.empty()) return; size_t cur = 0; while (true) { size_t next = s.find(", ", cur); if (next == string::npos) { set_from_string(s.substr(cur).c_str()); break; } else { set_from_string(s.substr(cur, next - cur).c_str()); cur = next + 2; } } } std::string Record::to_string() const { std::stringstream s; bool first = true; for (int i = 0; i < KEYWORD_TABLE_SIZE; ++i) if (keydata[i] != NULL) { if (first) first = false; else s << ","; s << keyword_name((dba_keyword)i) << "=" << keydata[i]->format(""); } for (vector::const_iterator i = m_vars.begin(); i != m_vars.end(); ++i) { if (first) first = false; else s << ","; s << wreport::varcode_format((*i)->code()) << "=" << (*i)->format(""); } return s.str(); } void Record::print(FILE* out) const { for (int i = 0; i < KEYWORD_TABLE_SIZE; ++i) if (keydata[i] != NULL) keydata[i]->print(out); for (vector::const_iterator i = m_vars.begin(); i != m_vars.end(); ++i) (*i)->print(out); } #if 0 void dba_record_diff(dba_record rec1, dba_record rec2, int* diffs, FILE* out) { int i; dba_record_cursor cur; /* First compare the keywords */ for (i = 0; i < KEYWORD_TABLE_SIZE; i++) { if (rec1->keydata[i] == NULL && rec2->keydata[i] == NULL) continue; else dba_var_diff(rec1->keydata[i], rec2->keydata[i], diffs, out); } /* Then compare the hash tables */ for (cur = dba_record_iterate_first(rec1); cur != NULL; cur = dba_record_iterate_next(rec1, cur)) { dba_varcode code = dba_var_code(cur->var); if (!dba_record_has_item(rec2, code)) { fprintf(out, "Variable %d%02d%03d only exists in first record\n", WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code)); (*diffs)++; } { dba_item item2; for (item2 = rec2->vars; item2 != NULL; item2 = item2->next) if (dba_var_code(item2->var) == code) { dba_var_diff(cur->var, item2->var, diffs, out); break; } } } /* Check for the items in the second one not present in the first one */ for (cur = dba_record_iterate_first(rec2); cur != NULL; cur = dba_record_iterate_next(rec2, cur)) { dba_varcode code = dba_var_code(cur->var); if (!dba_record_has_item(rec1, code)) { fprintf(out, "Variable %d%02d%03d only exists in second record\n", WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code)); (*diffs)++; } } } #endif MatchedRecord::MatchedRecord(const Record& r) : r(r) { } MatchedRecord::~MatchedRecord() { } matcher::Result MatchedRecord::match_var_id(int val) const { if (const wreport::Var* var = r.get("B33195")) { return var->enqi() == val ? matcher::MATCH_YES : matcher::MATCH_NO; } else return matcher::MATCH_NA; } matcher::Result MatchedRecord::match_station_id(int val) const { if (const wreport::Var* var = r.get("ana_id")) { return var->enqi() == val ? matcher::MATCH_YES : matcher::MATCH_NO; } else return matcher::MATCH_NA; } matcher::Result MatchedRecord::match_station_wmo(int block, int station) const { if (const wreport::Var* var = r.get("B01001")) { // Match block if (var->enqi() != block) return matcher::MATCH_NO; // If station was not requested, we are done if (station == -1) return matcher::MATCH_YES; // Match station if (const wreport::Var* var = r.get("B01002")) { if (var->enqi() != station) return matcher::MATCH_NO; return matcher::MATCH_YES; } } return matcher::MATCH_NA; } matcher::Result MatchedRecord::match_datetime(const DatetimeRange& range) const { Datetime dt = r.get_datetime(); if (dt.is_missing()) return matcher::MATCH_NA; return range.contains(dt) ? matcher::MATCH_YES : matcher::MATCH_NO; } matcher::Result MatchedRecord::match_coords(const LatRange& latrange, const LonRange& lonrange) const { matcher::Result r1 = matcher::MATCH_NA; if (const wreport::Var* var = r.get("lat")) r1 = latrange.contains(var->enqi()) ? matcher::MATCH_YES : matcher::MATCH_NO; else if (latrange.is_missing()) r1 = matcher::MATCH_YES; matcher::Result r2 = matcher::MATCH_NA; if (const wreport::Var* var = r.get("lon")) r2 = lonrange.contains(var->enqi()) ? matcher::MATCH_YES : matcher::MATCH_NO; else if (lonrange.is_missing()) r2 = matcher::MATCH_YES; if (r1 == matcher::MATCH_YES && r2 == matcher::MATCH_YES) return matcher::MATCH_YES; if (r1 == matcher::MATCH_NO || r2 == matcher::MATCH_NO) return matcher::MATCH_NO; return matcher::MATCH_NA; } matcher::Result MatchedRecord::match_rep_memo(const char* memo) const { if (const Var* var = r.get("rep_memo")) if (var->isset()) return strcmp(memo, var->enqc()) == 0 ? matcher::MATCH_YES : matcher::MATCH_NO; return matcher::MATCH_NA; } } } dballe-7.7/dballe/core/record-test.cc0000644000175000017500000002343012652630043014453 00000000000000#include "core/tests.h" #include "core/record.h" using namespace dballe::tests; using namespace dballe; using namespace std; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { #define fail_unless_int_is(keyvar, param, value) do { \ int found; \ int val; \ CHECKED(dba_record_##keyvar##_enqi(rec, param, &val, &found)); \ ensure_equals(found, 1); \ ensure_equals(val, value); \ } while (0) #define fail_unless_double_is(keyvar, param, value) do { \ int found; \ double val; \ CHECKED(dba_record_##keyvar##_enqd(rec, param, &val, &found)); \ ensure_equals(found, 1); \ ensure_equals(val, value); \ } while (0) #define fail_unless_char_is(keyvar, param, value) do { \ const char* val; \ CHECKED(dba_record_##keyvar##_enqc(rec, param, &val)); \ ensure(val != NULL); \ ensure_equals(string(val), string(value)); \ } while (0) add_method("keyword_name", []() { // Keyword name resolution using namespace dballe::core; wassert(actual(core::Record::keyword_byname("cippo") == DBA_KEY_ERROR).istrue()); wassert(actual(core::Record::keyword_byname("zzzip") == DBA_KEY_ERROR).istrue()); wassert(actual(core::Record::keyword_byname("ana_id") == DBA_KEY_ANA_ID).istrue()); wassert(actual(core::Record::keyword_byname_len("ana_idi", 6) == DBA_KEY_ANA_ID).istrue()); wassert(actual(core::Record::keyword_info(DBA_KEY_ANA_ID)->desc) == "Station database ID"); wassert(actual(core::Record::keyword_byname("yearmin") == DBA_KEY_YEARMIN).istrue()); wassert(actual(core::Record::keyword_info(DBA_KEY_YEARMIN)->desc) == "Year or minimum year queried"); wassert(actual(core::Record::keyword_byname("lat") == DBA_KEY_LAT).istrue()); wassert(actual(core::Record::keyword_info(DBA_KEY_LAT)->desc) == "Latitude"); wassert(actual(core::Record::keyword_byname("lon") == DBA_KEY_LON).istrue()); wassert(actual(core::Record::keyword_info(DBA_KEY_LON)->desc) == "Longitude"); }); add_method("get_set", []() { // Check that things don't exist at the beginning core::Record rec; wassert(actual(rec.get("ana_id")).isfalse()); wassert(actual(rec.get("lat")).isfalse()); wassert(actual(rec.get("B20001")).isfalse()); wassert(actual(rec.get("B20003")).isfalse()); // Set various things rec.set("ana_id", -10); rec.set("lat", 1234567); rec.set("lon", 76.54321); rec.set("yearmin", "1976"); rec.set("B20001", "456"); rec.set("B20003", "456"); // Check that they now exist wassert(actual(rec.get("ana_id")).istrue()); wassert(actual(rec.get("lat")).istrue()); wassert(actual(rec.get("B20001")).istrue()); wassert(actual(rec.get("B20003")).istrue()); // Check that they have the right value wassert(actual(rec.get("ana_id")->enqi()) == -10); wassert(actual(rec.get("ana_id")->enqd()) == -10.0); wassert(actual(rec.get("lon")->enqi()) == 7654321); wassert(actual(rec.get("lon")->enqd()) == 76.54321); wassert(actual(rec.get("lon")->enqc()) == "7654321"); wassert(actual(rec.get("lat")->enqd()) == 12.34567); wassert(actual(rec.get("yearmin")->enqd()) == 1976.0); wassert(actual(rec.get("B20001")->enqd()) == 4560.0); wassert(actual(rec.get("B20003")->enqd()) == 456); // See if unset works for keywords rec.unset("lat"); wassert(actual(rec.get("lat")).isfalse()); // See if unset works for variables rec.unset("B20001"); wassert(actual(rec.get("B20001")).isfalse()); /* fprintf(stderr, "IVAL: %d\n", ival); */ /* fprintf(stderr, "DVAL: %f\n", fval); */ /* { int i = 7654321; double f = (double)i / 100000; fprintf(stderr, "I: %d, F: %f\n", i, f); } */ // See if clear clears rec.clear(); wassert(actual(rec.get("lat")).isfalse()); wassert(actual(rec.get("B20003")).isfalse()); rec.clear(); wassert(actual(rec.get("lat")).isfalse()); wassert(actual(rec.get("B20003")).isfalse()); }); add_method("ident", []() { // This used to cause a segfault core::Record rec; rec.setc("ident", "nosort"); core::Record rec1; rec = rec; rec.setc("ident", "nosort"); }); add_method("comparisons", []() { core::Record rec; rec.set("ana_id", -10); rec.set("lat", 1234567); rec.set("lon", 76.54321); rec.set("yearmin", "1976"); rec.set("B20001", "456"); rec.set("B20003", "456"); core::Record rec1; rec1 = rec; wassert(actual(rec == rec1).istrue()); wassert(actual(rec1 == rec).istrue()); wassert(actual(!(rec != rec1)).istrue()); wassert(actual(!(rec1 != rec)).istrue()); rec1.seti("yearmin", 1975); wassert(actual(rec != rec1).istrue()); wassert(actual(rec1 != rec).istrue()); wassert(actual(!(rec == rec1)).istrue()); wassert(actual(!(rec1 == rec)).istrue()); rec1 = rec; wassert(actual(rec == rec1).istrue()); wassert(actual(rec1 == rec).istrue()); rec1.unset("yearmin"); wassert(actual(rec != rec1).istrue()); wassert(actual(rec1 != rec).istrue()); rec1 = rec; wassert(actual(rec == rec1).istrue()); wassert(actual(rec1 == rec).istrue()); rec1.set("B20001", "45"); wassert(actual(rec != rec1).istrue()); wassert(actual(rec1 != rec).istrue()); rec1 = rec; wassert(actual(rec == rec1).istrue()); wassert(actual(rec1 == rec).istrue()); rec1.unset("B20001"); wassert(actual(rec != rec1).istrue()); wassert(actual(rec1 != rec).istrue()); }); add_method("get_set_level", []() { core::Record rec; wassert(actual(rec.get_level()) == Level()); rec.set("leveltype1", 1); rec.set("l1", 0); rec.set("leveltype2", 2); rec.set("l2", 3); wassert(actual(rec.get_level()) == Level(1, 0, 2, 3)); rec.set(Level(9, 8)); wassert(actual(rec.enq("leveltype1", 0)) == 9); wassert(actual(rec.enq("l1", 0)) == 8); wassert(actual(rec.enq("leveltype2", 0)) == 0); wassert(actual(rec.enq("l2", 0)) == 0); wassert(actual(rec.get_level()) == Level(9, 8)); rec.set("leveltype1", 1); rec.setf("l1", "-"); wassert(actual(rec.get_level()) == Level(1)); }); add_method("get_set_trange", []() { core::Record rec; wassert(actual(rec.get_trange()) == Trange()); rec.set("pindicator", 11); rec.set("p1", 22); rec.set("p2", 33); wassert(actual(rec.get_trange()) == Trange(11, 22, 33)); rec.set(Trange(7, 6)); wassert(actual(rec.enq("pindicator", 0)) == 7); wassert(actual(rec.enq("p1", 0)) == 6); wassert(actual(rec.enq("p2", 0)) == 0); wassert(actual(rec.get_trange()) == Trange(7, 6)); }); add_method("get_set_datetime", []() { core::Record rec; rec.set(Datetime(2013, 11, 1, 12, 0, 0)); wassert(actual(rec.get_datetime()) == Datetime(2013, 11, 1, 12)); rec.set(Datetime(2012, 5, 15, 17, 30, 30)); Datetime dt = rec.get_datetime(); wassert(actual(dt) == Datetime(2012, 5, 15, 17, 30, 30)); }); add_method("iter", []() { // Test iteration using namespace dballe::core; core::Record rec; rec.set("priority", 1); rec.set(Datetime(2013, 11, 1, 12, 0, 0)); rec.set("var_related", "B12123"); unsigned count = 0; bool res = rec.iter_keys([&count](dba_keyword k, const wreport::Var& v) { ++count; return true; }); wassert(actual(res).istrue()); wassert(actual(count) == 8); }); add_method("extremes", []() { // Test querying extremes by Datetime core::Record rec; DatetimeRange dtr = wcallchecked(rec.get_datetimerange()); wassert(actual(dtr.min.is_missing()).istrue()); wassert(actual(dtr.max.is_missing()).istrue()); static const int NA = MISSING_INT; wassert(rec.set(DatetimeRange(2010, 1, 1, 0, 0, 0, NA, NA, NA, NA, NA, NA))); dtr = wcallchecked(rec.get_datetimerange()); wassert(actual(dtr.min) == Datetime(2010, 1, 1, 0, 0, 0)); wassert(actual(dtr.max.is_missing()).istrue()); wassert(rec.set(DatetimeRange(NA, NA, NA, NA, NA, NA, 2011, 2, 3, 4, 5, 6))); dtr = wcallchecked(rec.get_datetimerange()); wassert(actual(dtr.min.is_missing()).istrue()); wassert(actual(dtr.max) == Datetime(2011, 2, 3, 4, 5, 6)); wassert(rec.set(DatetimeRange(2010, 1, 1, 0, 0, 0, 2011, 2, 3, 4, 5, 6))); dtr = wcallchecked(rec.get_datetimerange()); wassert(actual(dtr.min) == Datetime(2010, 1, 1, 0, 0, 0)); wassert(actual(dtr.max) == Datetime(2011, 2, 3, 4, 5, 6)); }); } } test("core_record"); } dballe-7.7/dballe/core/varmatch.h0000644000175000017500000000226212652630043013667 00000000000000/* * core/varmatch - Variable matcher * * Copyright (C) 2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBA_CORE_VARMATCH_H #define DBA_CORE_VARMATCH_H #include #include namespace dballe { struct Varmatch { wreport::Varcode code; Varmatch(wreport::Varcode code); virtual ~Varmatch() {} virtual bool operator()(const wreport::Var&) const; static std::unique_ptr parse(const std::string& filter); }; } #endif dballe-7.7/dballe/core/aliases-test.cc0000644000175000017500000000150412652630043014614 00000000000000#include "core/tests.h" #include "core/aliases.h" using namespace dballe; using namespace dballe::tests; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("resolve", []() { wassert(actual_varcode(varcode_alias_resolve("block")) == WR_VAR(0, 1, 1)); wassert(actual_varcode(varcode_alias_resolve("station")) == WR_VAR(0, 1, 2)); wassert(actual_varcode(varcode_alias_resolve("height")) == WR_VAR(0, 7, 30)); wassert(actual_varcode(varcode_alias_resolve("heightbaro")) == WR_VAR(0, 7, 31)); wassert(actual_varcode(varcode_alias_resolve("name")) == WR_VAR(0, 1, 19)); wassert(actual_varcode(varcode_alias_resolve("cippolippo")) == 0); }); } } test("core_aliases"); } dballe-7.7/dballe/core/var.h0000644000175000017500000000433512652630043012655 00000000000000/* * dballe/var - DB-All.e specialisation of wreport variable * * Copyright (C) 2005--2011 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_CORE_VAR_H #define DBALLE_CORE_VAR_H /** @file * @ingroup core * Implement ::dba_var, an encapsulation of a measured variable. */ #include #include namespace dballe { /** * Convenience functions to quickly create variables from the local B table */ /// Resolve a comma-separated varcode list performing careful validation, inserting results in \a out void resolve_varlist(const std::string& varlist, std::set& out); /// Resolve a comma-separated varcode list performing careful validation, calling \a dest on each result void resolve_varlist(const std::string& varlist, std::function out); /// Create a new Var, copying \a var and all its attributes except the unset ones std::unique_ptr var_copy_without_unset_attrs(const wreport::Var& var); /** * Create a new Var with code \a code, copying the value from \a var and all * its attributes except the unset ones */ std::unique_ptr var_copy_without_unset_attrs(const wreport::Var& var, wreport::Varcode code); /** * Format the code to its string representation * * The string will be written to buf, which must be at least 7 bytes long */ void format_code(wreport::Varcode code, char* buf); /// Return \a code, or its DB-All.e equivalent wreport::Varcode map_code_to_dballe(wreport::Varcode code); } #endif /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/core/tests.h0000644000175000017500000000735212652630043013231 00000000000000#include #include #include #include #include #include #include #include #include #include #include #include namespace dballe { namespace tests { using namespace wreport::tests; /** * Check if a test can be run. * * This is used to implement extra test filtering features like glob matching * on group or test names. */ bool test_can_run(const std::string& group_name, const std::string& test_name); #if 0 // Some utility random generator functions static inline int rnd(int min, int max) { return min + (int) ((max - min) * (rand() / (RAND_MAX + 1.0))); } static inline double rnd(double min, double max) { return min + (int) ((max - min) * (rand() / (RAND_MAX + 1.0))); } static inline std::string rnd(int len) { std::string res; int max = rnd(1, len); for (int i = 0; i < max; i++) res += (char)rnd('a', 'z'); return res; } static inline bool rnd(double prob) { return (rnd(0, 100) < prob*100) ? true : false; } #endif // Message reading functions /// Return the pathname of a test file std::string datafile(const std::string& fname); std::unique_ptr open_test_data(const char* filename, File::Encoding type); BinaryMessage read_rawmsg(const char* filename, File::Encoding type); #if 0 /// Check that actual and expected have the same vars struct TestRecordValEqual { const dballe::Record& actual; const dballe::Record& expected; const char* name; bool with_missing_int; TestRecordValEqual(const dballe::Record& actual, const dballe::Record& expected, const char* name, bool with_missing_int=false) : actual(actual), expected(expected), name(name), with_missing_int(with_missing_int) {} void check() const; }; struct TestRecordVarsEqual { const dballe::Record& actual; dballe::Values expected; TestRecordVarsEqual(const dballe::Record& actual, const dballe::Record& expected) : actual(actual), expected(expected) {} TestRecordVarsEqual(const dballe::Record& actual, const dballe::Values& expected) : actual(actual), expected(expected) {} void check() const; }; #endif struct ActualRecord : public wreport::tests::Actual { ActualRecord(const dballe::Record& actual) : wreport::tests::Actual(actual) {} #if 0 TestRecordValEqual equals(const Record& expected, const char* name) { return TestRecordValEqual(this->actual, expected, name); } TestRecordValEqual equals_with_missing_int(const Record& expected, const char* name) { return TestRecordValEqual(this->actual, expected, name, true); } #endif /// Check that actual and expected have the same vars void vars_equal(const Record& expected) const { vars_equal(Values(expected)); } /// Check that actual and expected have the same vars void vars_equal(const Values& expected) const; }; // Set a record from a ", "-separated string of assignments void set_record_from_string(Record& rec, const std::string& s); std::unique_ptr record_from_string(const std::string& s); std::unique_ptr query_from_string(const std::string& s); core::Query core_query_from_string(const std::string& s); struct ActualMatcherResult : public Actual { using Actual::Actual; void operator==(int expected) const; void operator!=(int expected) const; }; inline ActualMatcherResult actual_matcher_result(int actual) { return ActualMatcherResult(actual); } using wreport::tests::actual; inline dballe::tests::ActualRecord actual(const dballe::Record& actual) { return dballe::tests::ActualRecord(actual); } inline ActualCString actual(const dballe::Ident& ident) { return ActualCString(ident); } } } dballe-7.7/dballe/core/defs.cc0000644000175000017500000000675412652630043013153 00000000000000#include "defs.h" #include #include #include #include #include #include "dballe/core/vasprintf.h" #include #include #include using namespace std; using namespace wreport; namespace dballe { std::ostream& operator<<(std::ostream& out, const Level& l) { l.to_stream(out); return out; } std::ostream& operator<<(std::ostream& out, const Trange& l) { l.to_stream(out); return out; } Ident::Ident(const char* value) : value(value ? strdup(value) : nullptr) {} Ident::Ident(const Ident& o) : value(o.value ? strdup(o.value) : nullptr) {} Ident::Ident(Ident&& o) : value(o.value) { o.value = nullptr; } Ident::~Ident() { free(value); } Ident& Ident::operator=(const Ident& o) { if (value == o.value) return *this; free(value); value = o.value ? strdup(o.value) : nullptr; return *this; } Ident& Ident::operator=(Ident&& o) { if (value == o.value) return *this; free(value); if (o.value) { value = strdup(o.value); o.value = nullptr; } else value = nullptr; return *this; } Ident& Ident::operator=(const char* o) { if (value) free(value); value = o ? strdup(o) : nullptr; return *this; } Ident& Ident::operator=(const std::string& o) { if (value) free(value); value = strndup(o.c_str(), o.size()); return *this; } void Ident::clear() { free(value); value = 0; } int Ident::compare(const Ident& o) const { if (!value && !o.value) return 0; if (!value && o.value) return -1; if (value && !o.value) return 1; return strcmp(value, o.value); } int Ident::compare(const char* o) const { if (!value && !o) return 0; if (!value && o) return -1; if (value && !o) return 1; return strcmp(value, o); } int Ident::compare(const std::string& o) const { if (!value) return -1; return strcmp(value, o.c_str()); } Ident::operator std::string() const { if (!value) throw error_consistency("ident is not set"); return std::string(value); } std::ostream& operator<<(std::ostream& out, const Coords& c) { out << "(" << setprecision(5) << c.dlat() << "," << setprecision(5) << c.dlon() << ")"; return out; } std::ostream& operator<<(std::ostream& out, const Date& dt) { dt.to_stream_iso8601(out); return out; } std::ostream& operator<<(std::ostream& out, const Time& dt) { dt.to_stream_iso8601(out); return out; } std::ostream& operator<<(std::ostream& out, const Datetime& dt) { dt.to_stream_iso8601(out); return out; } std::ostream& operator<<(std::ostream& out, const DatetimeRange& dtr) { if (dtr.min == dtr.max) dtr.min.to_stream_iso8601(out); else { out << "("; dtr.min.to_stream_iso8601(out); out << " to "; dtr.max.to_stream_iso8601(out); out << ")"; } return out; } std::ostream& operator<<(std::ostream& out, const LatRange& lr) { double dmin, dmax; lr.get(dmin, dmax); out << "(" << setprecision(5) << dmin << " to " << setprecision(5) << dmax << ")"; return out; } std::ostream& operator<<(std::ostream& out, const LonRange& lr) { double dmin, dmax; lr.get(dmin, dmax); out << "(" << setprecision(5) << dmin << " to " << setprecision(5) << dmax << ")"; return out; } std::ostream& operator<<(std::ostream& out, const Ident& i) { if (i.is_missing()) out << "(null)"; else out << (const char*)i; return out; } } dballe-7.7/dballe/core/varmatch-test.cc0000644000175000017500000001347512652630043015012 00000000000000#include "tests.h" #include "var.h" #include "varmatch.h" using namespace wreport; using namespace dballe; using namespace dballe::tests; using namespace std; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("int", []() { Var var(varinfo(WR_VAR(0, 1, 1)), 42); wassert(actual((*Varmatch::parse("B01001<43"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01001<42"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01001<41"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01001<=43"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01001<=42"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01001<=41"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01001>41"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01001>42"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01001>43"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01001>=41"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01001>=42"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01001>=43"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01001==42"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01001=42"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01001==43"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01001=43"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01001<>43"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01001<>42"))(var)).isfalse()); wassert(actual((*Varmatch::parse("41<=B01001<=42"))(var)).istrue()); wassert(actual((*Varmatch::parse("42<=B01001<=42"))(var)).istrue()); wassert(actual((*Varmatch::parse("42<=B01001<=43"))(var)).istrue()); wassert(actual((*Varmatch::parse("40<=B01001<=41"))(var)).isfalse()); }); add_method("decimal", []() { Var var(varinfo(WR_VAR(0, 12, 101)), 273.15); wassert(actual((*Varmatch::parse("B12101<274"))(var)).istrue()); wassert(actual((*Varmatch::parse("B12101<273.15"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B12101<273"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B12101<=274"))(var)).istrue()); wassert(actual((*Varmatch::parse("B12101<=273.15"))(var)).istrue()); wassert(actual((*Varmatch::parse("B12101<=273"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B12101>273"))(var)).istrue()); wassert(actual((*Varmatch::parse("B12101>273.15"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B12101>274"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B12101>=273"))(var)).istrue()); wassert(actual((*Varmatch::parse("B12101>=273.15"))(var)).istrue()); wassert(actual((*Varmatch::parse("B12101>=274"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B12101==273.15"))(var)).istrue()); wassert(actual((*Varmatch::parse("B12101=273.15"))(var)).istrue()); wassert(actual((*Varmatch::parse("B12101==274"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B12101=274"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B12101<>274"))(var)).istrue()); wassert(actual((*Varmatch::parse("B12101<>273.15"))(var)).isfalse()); wassert(actual((*Varmatch::parse("273<=B12101<=273.15"))(var)).istrue()); wassert(actual((*Varmatch::parse("273.15<=B12101<=273.15"))(var)).istrue()); wassert(actual((*Varmatch::parse("273.15<=B12101<=274"))(var)).istrue()); wassert(actual((*Varmatch::parse("272<=B12101<=273"))(var)).isfalse()); }); add_method("string", []() { Var var(varinfo(WR_VAR(0, 1, 11)), "enrico"); wassert(actual((*Varmatch::parse("B01011emanuele"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01011>enrico"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01011>paolo"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01011>=emanuele"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01011>=enrico"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01011>=paolo"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01011==enrico"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01011=enrico"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01011==paolo"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01011=paolo"))(var)).isfalse()); wassert(actual((*Varmatch::parse("B01011<>paolo"))(var)).istrue()); wassert(actual((*Varmatch::parse("B01011<>enrico"))(var)).isfalse()); wassert(actual((*Varmatch::parse("emanuele<=B01011<=enrico"))(var)).istrue()); wassert(actual((*Varmatch::parse("enrico<=B01011<=enrico"))(var)).istrue()); wassert(actual((*Varmatch::parse("enrico<=B01011<=paolo"))(var)).istrue()); wassert(actual((*Varmatch::parse("daniele<=B01011<=emanuele"))(var)).isfalse()); }); } } test("core_varmatch"); } dballe-7.7/dballe/core/csv.h0000644000175000017500000001115512652630043012656 00000000000000/* * dballe/csv - CSV utility functions * * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBA_CSV_H #define DBA_CSV_H /** @file * @ingroup core * Routines to parse data in CSV format */ #include #include #include #include #include namespace dballe { /** * Parse a CSV line. * * @param in * The file where to read from * @param cols * The parsed columns. * @return * true if a new line was found, else false */ bool csv_read_next(FILE* in, std::vector& cols); class CSVReader { protected: std::istream* in; int next_char(); public: /** * If true, the input stream will be deleted upon destruction. * If false, it will be left alone. */ bool close_on_exit; /// Last line read std::string line; /// Parsed CSV columns for the last line read std::vector cols; CSVReader(); CSVReader(std::istream& in); CSVReader(const std::string& pathname); ~CSVReader(); /** * Open the given file and sets close_on_exit to true */ void open(const std::string& pathname); /** * Sets in to 0. * If close_on_exit is true, close the currently opened file. */ void close(); /** * Return the given column, as an integer. * * A missing value raises an exception. */ int as_int(unsigned col) const; /** * Return the given column, as an integer. * * A missing value is returned as MISSING_INT. */ int as_int_withmissing(unsigned col) const; /** * Return the given column, as a Varcode. * * A missing value raises an exception. */ wreport::Varcode as_varcode(unsigned col) const; /** * Find the first line where the given column exists and starts with a * number. * * This can be used to skip titles and empty lines, moving to the start of * the real data. Real data is identified by using a column that starts * with text in the headers and number in the data. * * @returns true if a data line has been found, false if we reached EOF */ bool move_to_data(unsigned number_col=0); /// Read the next CSV line, returning false if EOF is reached bool next(); static std::string unescape(const std::string& csvstr); }; // TODO: CSV readers allowing to peek on the next line without consuming it, to // allow the Msg parser to stop at msg boundary after peeking at a line // also, stripping newlines at end of lines // also, reading from istream // also, de-escaping strings (if they start with quote) /** * Output a string value, quoted if needed according to CSV rules */ void csv_output_quoted_string(std::ostream& out, const std::string& str); class CSVWriter { protected: std::string row; public: virtual ~CSVWriter(); /// Add an empty value to the current row void add_value_empty(); /// Add a value to the current row, without any escaping void add_value_raw(const char* str); /// Add a value to the current row, without any escaping void add_value_raw(const std::string& str); /// Add an int value to the current row void add_value(int val); /// Add an int value that can potentially be missing void add_value_withmissing(int val); /// Add an int value to the current row void add_value(unsigned val); /// Add an int value to the current row void add_value(uint64_t val); /// Add an int value to the current row void add_value(wreport::Varcode val); /// Add a variable value void add_var_value(const wreport::Var& val); /// Add a string to the current row void add_value(const char* val); /// Add a string to the current row void add_value(const std::string& val); /// Write the current line to the output file, and start a new one virtual void flush_row() = 0; }; } /* vim:set ts=4 sw=4: */ #endif dballe-7.7/dballe/core/structbuf.h0000644000175000017500000000737312652630043014113 00000000000000/* * core/structbuf - memory or file-backed storage of structures * * Copyright (C) 2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_CORE_STRUCTBUF_H #define DBALLE_CORE_STRUCTBUF_H #include #include #include #include namespace dballe { namespace structbuf { int make_anonymous_tmpfile(); void write_buffer(int fd, void* buf, size_t size); } /** * Buffer of simple structures that becomes file backed if it grows beyond a * certain size. * * bufsize is the number of T items that we keep in memory before becoming * file-backed. */ template class Structbuf { protected: /** * In-memory buffer using during appending. When it becomes full, it is * flushed out to a temporary file. */ T* membuf = nullptr; /// Number of items in membuf unsigned membuf_last = 0; /** * Memory area used for reading. It points to membuf if we are * memory-backed, or it is the mmap view of the file if we are file-backed */ const T* readbuf = (const T*)MAP_FAILED; /// Number of items appended so far size_t m_count = 0; /// Unix file descriptor to the temporary file, or -1 if we are memory /// backed int tmpfile_fd = -1; public: Structbuf() : membuf(new T[bufsize]) { } ~Structbuf() { delete[] membuf; if (tmpfile_fd != -1) { if (readbuf != MAP_FAILED) munmap((void*)readbuf, m_count * sizeof(T)); ::close(tmpfile_fd); } } /// Get the number of structures that have been added to the buffer so far size_t size() const { return m_count; } /// Return true if the buffer has become file-backed bool is_file_backed() const { return tmpfile_fd != -1; } /// Append an item to the buffer void append(const T& val) { if (readbuf != MAP_FAILED) throw wreport::error_consistency("writing to a Structbuf that is already being read"); if (membuf_last == bufsize) write_to_file(); membuf[membuf_last++] = val; ++m_count; } /// Stop appending and get ready to read back the data void ready_to_read() { if (tmpfile_fd == -1) readbuf = membuf; else { // Flush the remaining memory data to file if (membuf_last) write_to_file(); // mmap the file for reading readbuf = (const T*)mmap(nullptr, m_count * sizeof(T), PROT_READ, MAP_SHARED, tmpfile_fd, 0); if (readbuf == MAP_FAILED) throw wreport::error_system("cannot map temporary file contents to memory"); } } /// Read back an item const T& operator[](size_t idx) const { return readbuf[idx]; } protected: void write_to_file() { if (tmpfile_fd == -1) tmpfile_fd = structbuf::make_anonymous_tmpfile(); structbuf::write_buffer(tmpfile_fd, membuf, sizeof(T) * membuf_last); membuf_last = 0; } }; } #endif dballe-7.7/dballe/core/values-test.cc0000644000175000017500000000050412652630043014471 00000000000000#include "core/tests.h" #include "core/values.h" using namespace std; using namespace dballe::tests; using namespace dballe; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("empty", []() { }); } } test("core_values"); } dballe-7.7/dballe/core/structbuf-test.cc0000644000175000017500000000360712652630043015222 00000000000000#include "tests.h" #include "structbuf.h" using namespace dballe; using namespace wreport; using namespace dballe::tests; using namespace std; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { // Test an in-memory structbuf add_method("memory", []() { Structbuf buf; wassert(actual(buf.size()) == 0); wassert(actual(buf.is_file_backed()).isfalse()); buf.append(1); wassert(actual(buf.size()) == 1); wassert(actual(buf.is_file_backed()).isfalse()); buf.append(2); wassert(actual(buf.size()) == 2); wassert(actual(buf.is_file_backed()).isfalse()); buf.append(3); wassert(actual(buf.size()) == 3); wassert(actual(buf.is_file_backed()).isfalse()); buf.ready_to_read(); for (unsigned i = 0; i < 3; ++i) wassert(actual(buf[i]) == i + 1); }); // Test an file-backed structbuf add_method("file", []() { Structbuf buf; buf.append(1); buf.append(2); buf.append(3); wassert(actual(buf.size()) == 3); wassert(actual(buf.is_file_backed()).isfalse()); buf.append(4); wassert(actual(buf.size()) == 4); wassert(actual(buf.is_file_backed()).istrue()); buf.append(5); wassert(actual(buf.size()) == 5); buf.append(6); wassert(actual(buf.size()) == 6); buf.append(7); wassert(actual(buf.size()) == 7); buf.append(8); wassert(actual(buf.size()) == 8); buf.ready_to_read(); for (unsigned i = 0; i < 8; ++i) wassert(actual(buf[i]) == i + 1); }); } } test("core_structbuf"); } dballe-7.7/dballe/core/aliases.gperf0000644000175000017500000000476712652630043014373 00000000000000/* * wreport/aliases - Aliases for commonly used variable codes * * Copyright (C) 2005--2011 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ %define slot-name alias %define class-name VarcodeAliases %define lookup-function-name find %struct-type %language=C++ %global-table %compare-strncmp /* Using %switch may be faster (remember to check when doing optimizations) */ %{ #include #include using namespace wreport; namespace dballe { %} struct aliasdef { const char* alias; Varcode var; }; %% block, WR_VAR(0, 1, 1) station, WR_VAR(0, 1, 2) height, WR_VAR(0, 7, 30) heightbaro, WR_VAR(0, 7, 31) name, WR_VAR(0, 1, 19) z, WR_VAR(0, 10, 3) p, WR_VAR(0, 10, 4) mslp, WR_VAR(0, 10, 51) u, WR_VAR(0, 11, 3) v, WR_VAR(0, 11, 4) t, WR_VAR(0, 12, 101) td, WR_VAR(0, 12, 103) tmax, WR_VAR(0, 12, 11) tmin, WR_VAR(0, 12, 12) q, WR_VAR(0, 13, 1) rh, WR_VAR(0, 13, 3) tp, WR_VAR(0, 13, 11) mwd, WR_VAR(0, 22, 1) swh, WR_VAR(0, 22, 70) pp1d, WR_VAR(0, 22, 71) mwp, WR_VAR(0, 22, 74) conf, WR_VAR(0, 33, 7) data_id, WR_VAR(0, 33, 195) no, WR_VAR(0, 15, 192) no2, WR_VAR(0, 15, 193) o3, WR_VAR(0, 15, 194) pm10, WR_VAR(0, 15, 195) %% Varcode varcode_alias_resolve(const char* alias) { struct aliasdef* res = VarcodeAliases::find(alias, strlen(alias)); if (res == NULL) return 0; else return res->var; } Varcode varcode_alias_resolve_substring(const char* alias, int len) { struct aliasdef* res = VarcodeAliases::find(alias, len); if (res == NULL) return 0; else return res->var; } wreport::Varcode varcode_alias_resolve(const std::string& alias) { struct aliasdef* res = VarcodeAliases::find(alias.data(), alias.size()); if (res == NULL) return 0; else return res->var; } } /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/core/arrayfile.cc0000644000175000017500000000124712652630043014200 00000000000000#include "arrayfile.h" using namespace std; namespace dballe { namespace core { ArrayFile::ArrayFile(Encoding type) : File("array", NULL, false), file_type(type), current(0) { } ArrayFile::~ArrayFile() { } File::Encoding ArrayFile::encoding() const { return file_type; } void ArrayFile::write(const std::string& msg) { msgs.push_back(BinaryMessage(file_type)); msgs.back().data = msg; msgs.back().pathname = m_name; msgs.back().offset = msgs.size() - 1; msgs.back().index = msgs.size() - 1; } BinaryMessage ArrayFile::read() { if (current >= msgs.size()) return BinaryMessage(file_type); else return msgs[current++]; } } } dballe-7.7/dballe/core/json.h0000644000175000017500000000562312652630043013037 00000000000000#ifndef DBALLE_CORE_JSON_H #define DBALLE_CORE_JSON_H #include #include #include #include #include #include namespace dballe { namespace core { /** * JSON serializer * * It is called with a sequence of sax-like events, and appends the resulting * JSON to a string. * * The JSON output is all in one line, so that end of line can be used as * separator between distinct JSON records. */ class JSONWriter { protected: enum State { LIST_FIRST, LIST, MAPPING_KEY_FIRST, MAPPING_KEY, MAPPING_VAL, }; std::ostream& out; std::vector stack; /// Append whatever separator is needed (if any) before a new value void val_head(); void jputc(char c); void jputs(const char* s); public: JSONWriter(std::ostream& out); ~JSONWriter(); /** * Reset the serializer state, to cancel the current output and prepare for * a new one */ void reset(); void start_list(); void end_list(); void start_mapping(); void end_mapping(); void add_null(); void add_bool(bool val); void add_int(int val); void add_double(double val); void add_cstring(const char* val); void add_string(const std::string& val); void add_number(const std::string& val); void add_level(const Level& val); void add_trange(const Trange& val); void add_datetime(const Datetime& val); void add_coords(const Coords& val); void add_var(const wreport::Var& val); void add_break(); void add(const std::string& val) { add_string(val); } void add(const char* val) { add_cstring(val); } void add(double val) { add_double(val); } void add(int val) { add_int(val); } void add(bool val) { add_bool(val); } void add(wreport::Varcode val) { add_int(val); } void add(const Level& val) { add_level(val); } void add(const Trange& val) { add_trange(val); } void add(const Datetime& val) { add_datetime(val); } void add(const Coords& val) { add_coords(val); } void add(const wreport::Var& val) { add_var(val); } template void add(const char* a, T b) { add_cstring(a); add(b); } template void add_list(const T& val) { start_list(); for (const auto& i : val) add(i); end_list(); } }; /** * JSON sax-like parser. */ class JSONReader { public: virtual void on_start_list() = 0; virtual void on_end_list() = 0; virtual void on_start_mapping() = 0; virtual void on_end_mapping() = 0; virtual void on_add_null() = 0; virtual void on_add_bool(bool val) = 0; virtual void on_add_int(int val) = 0; virtual void on_add_double(double val) = 0; virtual void on_add_string(const std::string& val) = 0; // Parse a stream void parse(std::istream& in); }; } } #endif dballe-7.7/dballe/core/csv.cc0000644000175000017500000004323212652630043013015 00000000000000/* * dballe/csv - CSV utility functions * * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ /* * The FormatInt class is Copyright (c) 2012, Victor Zverovich * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "dballe/var.h" #include #include #include #include #include #include #include #include #include using namespace std; using namespace wreport; namespace dballe { CSVReader::CSVReader() : in(0), close_on_exit(false) {} CSVReader::CSVReader(std::istream& in) : in(&in), close_on_exit(false) {} CSVReader::CSVReader(const std::string& pathname) : in(0), close_on_exit(false) { open(pathname); } CSVReader::~CSVReader() {} void CSVReader::open(const std::string& pathname) { close(); close_on_exit = true; in = new ifstream(pathname.c_str()); if (in->fail()) error_system::throwf("cannot open file %s", pathname.c_str()); } void CSVReader::close() { if (in && close_on_exit) delete in; in = 0; close_on_exit = true; } std::string CSVReader::unescape(const std::string& csvstr) { if (csvstr.empty()) return csvstr; if (csvstr[0] != '"') return csvstr; if (csvstr.size() == 1) return csvstr; string res; bool escape = false; for (string::const_iterator i = csvstr.begin() + 1; i != csvstr.end(); ++i) { if (*i == '"') { if (!escape) escape = true; else { res += *i; escape = false; } } else res += *i; } return res; } int CSVReader::as_int(unsigned col) const { if (cols[col].empty()) error_consistency::throwf("cannot parse a number from column %u, which is empty", col); return strtoul(cols[col].c_str(), 0, 10); } int CSVReader::as_int_withmissing(unsigned col) const { if (cols[col].empty()) return MISSING_INT; return strtoul(cols[col].c_str(), 0, 10); } wreport::Varcode CSVReader::as_varcode(unsigned col) const { return resolve_varcode(cols[col]); } bool CSVReader::move_to_data(unsigned number_col) { while (true) { if (number_col < cols.size() && (cols[number_col].empty() || isdigit(cols[number_col][0]) || cols[number_col][0] == '-')) break; if (!next()) return false; } return true; } int CSVReader::next_char() { int res = in->get(); if (res == EOF && !in->eof()) throw error_system("reading a character from CSV input"); return res; } bool CSVReader::next() { if (!in) return false; cols.clear(); // Tokenize the input line enum State { BEG, COL, QCOL, EQCOL, HALFEOL } state = BEG; string col; int c; while ((c = next_char()) != EOF) { switch (state) { // Look for the beginning of a column value case BEG: switch (c) { case '"': state = QCOL; break; case ',': state = BEG; cols.push_back(col); col.clear(); break; case '\r': state = HALFEOL; break; case '\n': cols.push_back(col); return true; default: state = COL; col += c; break; } break; // Inside a column value case COL: switch (c) { case ',': state = BEG; cols.push_back(col); col.clear(); break; case '\r': state = HALFEOL; break; case '\n': cols.push_back(col); return true; default: col += c; break; } break; // Inside a quoted column value case QCOL: switch (c) { case '\"': state = EQCOL; break; default: col += c; break; } break; // After a quote character found inside a quoted column value case EQCOL: switch (c) { // The quote marked the end of the value case ',': state = BEG; cols.push_back(col); col.clear(); break; case '\r': state = HALFEOL; break; case '\n': cols.push_back(col); return true; // The quote was an escape default: state = QCOL; col += c; break; } break; // After \r was found case HALFEOL: switch (c) { case '\n': cols.push_back(col); return true; default: state = COL; col += '\r'; col += c; break; } break; } } if (state == BEG) return false; if (!col.empty()) cols.push_back(col); return true; } bool csv_read_next(FILE* in, std::vector& cols) { char line[2000]; char* tok; char* stringp; if (fgets(line, 2000, in) == NULL) return false; cols.clear(); for (stringp = line; (tok = strsep(&stringp, ",")) != NULL; ) cols.push_back(tok); return true; } void csv_output_quoted_string(ostream& out, const std::string& str) { if (str.find_first_of("\",") != string::npos) { out << "\""; for (string::const_iterator i = str.begin(); i != str.end(); ++i) { if (*i == '"') out << '"'; out << *i; } out << "\""; } else out << str; } namespace { // FormatInt by Victor Zverovich // See https://github.com/vitaut/format const char DIGITS[] = "0001020304050607080910111213141516171819" "2021222324252627282930313233343536373839" "4041424344454647484950515253545556575859" "6061626364656667686970717273747576777879" "8081828384858687888990919293949596979899"; class FormatInt { private: // Buffer should be large enough to hold all digits (digits10 + 1), // a sign and a null character. enum {BUFFER_SIZE = std::numeric_limits::digits10 + 3}; char buffer_[BUFFER_SIZE]; char *str_; // Formats value in reverse and returns the number of digits. char *FormatDecimal(uint64_t value) { char *buffer_end = buffer_ + BUFFER_SIZE; *--buffer_end = '\0'; while (value >= 100) { // Integer division is slow so do it for a group of two digits instead // of for every digit. The idea comes from the talk by Alexandrescu // "Three Optimization Tips for C++". See speed-test for a comparison. unsigned index = (value % 100) * 2; value /= 100; *--buffer_end = DIGITS[index + 1]; *--buffer_end = DIGITS[index]; } if (value < 10) { *--buffer_end = static_cast('0' + value); return buffer_end; } unsigned index = static_cast(value * 2); *--buffer_end = DIGITS[index + 1]; *--buffer_end = DIGITS[index]; return buffer_end; } public: explicit FormatInt(int value) { unsigned abs_value = value; bool negative = value < 0; if (negative) abs_value = 0 - value; str_ = FormatDecimal(abs_value); if (negative) *--str_ = '-'; } explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {} explicit FormatInt(uint64_t value) : str_(FormatDecimal(value)) {} unsigned size() const { return buffer_ + BUFFER_SIZE - str_ - 1; } const char *c_str() const { return str_; } std::string str() const { return str_; } }; } CSVWriter::~CSVWriter() { } void CSVWriter::add_value_empty() { if (!row.empty()) row += ','; } void CSVWriter::add_value_raw(const char* str) { if (!row.empty()) row += ','; row.append(str); } void CSVWriter::add_value_raw(const std::string& str) { if (!row.empty()) row += ','; row.append(str); } void CSVWriter::add_value(uint64_t val) { FormatInt fmt(val); add_value_raw(fmt.c_str()); } void CSVWriter::add_value(unsigned val) { FormatInt fmt(val); add_value_raw(fmt.c_str()); } void CSVWriter::add_value(int val) { FormatInt fmt(val); add_value_raw(fmt.c_str()); } void CSVWriter::add_value_withmissing(int val) { if (val == MISSING_INT) { if (!row.empty()) row += ','; } else { add_value(val); } } void CSVWriter::add_value(wreport::Varcode val) { if (!row.empty()) row += ','; switch (WR_VAR_F(val)) { case 0: row += 'B'; break; case 1: row += 'R'; break; case 2: row += 'C'; break; case 3: row += 'D'; break; } unsigned index = WR_VAR_X(val) * 2; row += DIGITS[index]; row += DIGITS[index + 1]; FormatInt fmt(WR_VAR_Y(val)); for (unsigned i = 0; i < 3-fmt.size(); ++i) row += '0'; row.append(fmt.c_str()); } void CSVWriter::add_var_value(const wreport::Var& var) { if (!var.isset()) { add_value_empty(); return; } switch (var.info()->type) { case Vartype::String: add_value(var.enqc()); break; case Vartype::Binary: // Skip binary variables, that cannot really be encoded in CSV add_value_empty(); break; case Vartype::Integer: case Vartype::Decimal: add_value(var.enqi()); break; } } void CSVWriter::add_value(const char* val) { if (!row.empty()) row += ','; if (!*val) return; row += '"'; for ( ; *val; ++val) { if (*val == '"') row += '"'; row += *val; } row += '"'; } void CSVWriter::add_value(const std::string& val) { if (!row.empty()) row += ','; if (val.empty()) return; row += '"'; for (string::const_iterator i = val.begin(); i != val.end(); ++i) { if (*i == '"') row += '"'; row += *i; } row += '"'; } #if 0 void test_dba_csv() { { /* Test dba_item handling */ dba_item chain = NULL, item = NULL; CHECKED(dba_item_obtain(&chain, "cippo", &item)); fail_unless_chain_is(chain, "cippo", chain); fail_unless_chain_hasnt(chain, "lippo"); CHECKED(dba_item_obtain(&chain, "lippo", &item)); fail_unless(item != chain); fail_unless_chain_is(chain, "cippo", chain); fail_unless_chain_is(chain, "lippo", item); dba_item_remove(&chain, "cippo"); fail_unless(item == chain); fail_unless_chain_hasnt(chain, "cippo"); fail_unless_chain_is(chain, "lippo", item); dba_item_remove(&chain, "lippo"); fail_unless(chain == NULL); dba_item_delete(chain); } { /* Hash table handling */ dba_record rec; dba_item item = NULL; CHECKED(dba_record_create(&rec)); fail_unless(rec != NULL); fail_unless_hasnt(rec, "cippo"); CHECKED(dba_record_obtain_item(rec, "cippo", &item)); fail_unless(item != NULL); fail_unless_has(rec, "cippo"); item->value = strdup("cippo"); fail_unless_hasnt(rec, "lippo"); CHECKED(dba_record_obtain_item(rec, "lippo", &item)); fail_unless(item != NULL); fail_unless_has(rec, "cippo"); fail_unless_has(rec, "lippo"); item->value = strdup("lippo"); fail_unless_is_it(rec, "cippo"); fail_unless_is_it(rec, "lippo"); dba_record_remove_item(rec, "cippo"); fail_unless_hasnt(rec, "cippo"); fail_unless_has(rec, "lippo"); dba_record_remove_item(rec, "cippo"); fail_unless_hasnt(rec, "cippo"); fail_unless_has(rec, "lippo"); dba_record_remove_item(rec, "pippo"); fail_unless_hasnt(rec, "cippo"); fail_unless_has(rec, "lippo"); dba_record_remove_item(rec, "lippo"); fail_unless_hasnt(rec, "cippo"); fail_unless_hasnt(rec, "lippo"); dba_record_remove_item(rec, "pippo"); fail_unless_hasnt(rec, "cippo"); fail_unless_hasnt(rec, "lippo"); dba_record_delete(rec); } { /* Keyword info handling */ dba_varinfo* info; int index; fail_unless(dba_record_keyword("cippo", &index) == NULL); fail_unless(dba_record_keyword("zzzip", &index) == NULL); fail_unless((info = dba_record_keyword("idstaz_select", &index)) != NULL); fail_unless(strcmp(info->desc, "Unique station identifier") == 0); fail_unless((info = dba_record_keyword("yearmin", &index)) != NULL); fail_unless(strcmp(info->desc, "Year or minimum year queried") == 0); fail_unless((info = dba_record_keyword("lat", &index)) != NULL); fail_unless(strcmp(info->desc, "Latitude") == 0); fail_unless((info = dba_record_keyword("lon", &index)) != NULL); fail_unless(strcmp(info->desc, "Longitude") == 0); } { /* Record gets and sets */ dba_err err; int ival; dba_record rec; CHECKED(dba_record_create(&rec)); err = dba_enqi(rec, "idstaz_select", &ival); fail_unless(err == DBA_ERROR); fail_unless(dba_error_get_code() == DBA_ERR_TYPE); err = dba_enqi(rec, "lat", &ival); fail_unless(err == DBA_ERROR); fail_unless(dba_error_get_code() == DBA_ERR_NOTFOUND); err = dba_seti(rec, "idstaz_select", 1); fail_unless(err == DBA_ERROR); fail_unless(dba_error_get_code() == DBA_ERR_TYPE); CHECKED(dba_seti(rec, "ana_id", -10)); CHECKED(dba_seti(rec, "lat", 1234567)); CHECKED(dba_setd(rec, "lon", 76.54321)); CHECKED(dba_setc(rec, "yearmin", "1976")); CHECKED(dba_setc(rec, "B02121", "456")); fail_unless_int_is(rec, "ana_id", -10); fail_unless_real_is(rec, "ana_id", -10.0); fail_unless_int_is(rec, "lon", 7654321); /*fail_unless_float_is(rec, "lon", 76.54321);*/ fail_unless_real_is(rec, "lon", 76.54321); fail_unless_char_is(rec, "lon", "7654321"); fail_unless_int_is(rec, "lat", 1234567); /*fail_unless_float_is(rec, "lat", 12.34567);*/ fail_unless_real_is(rec, "lat", 12.34567); fail_unless_char_is(rec, "lat", "1234567"); fail_unless_int_is(rec, "yearmin", 1976); fail_unless_float_is(rec, "yearmin", 1976); fail_unless_real_is(rec, "yearmin", 1976); fail_unless_char_is(rec, "yearmin", "1976"); fail_unless_int_is(rec, "B02121", 456); /*fail_unless_float_is(rec, "B02121", 45600000000.0)*/; fail_unless_real_is(rec, "B02121", 45600000000.0); fail_unless_char_is(rec, "B02121", "456"); CHECKED(dba_unset(rec, "lat")); err = dba_enqi(rec, "lat", &ival); fail_unless(err == DBA_ERROR); fail_unless(dba_error_get_code() == DBA_ERR_NOTFOUND); /* fprintf(stderr, "IVAL: %d\n", ival); */ /* fprintf(stderr, "DVAL: %f\n", fval); */ /* { int i = 7654321; double f = (double)i / 100000; fprintf(stderr, "I: %d, F: %f\n", i, f); } */ /* See if clear clears */ dba_record_clear(rec); err = dba_enqi(rec, "lat", &ival); fail_unless(err == DBA_ERROR); fail_unless(dba_error_get_code() == DBA_ERR_NOTFOUND); dba_record_clear(rec); err = dba_enqi(rec, "lat", &ival); fail_unless(err == DBA_ERROR); fail_unless(dba_error_get_code() == DBA_ERR_NOTFOUND); dba_record_delete(rec); } } #endif } // namespace dballe /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/core/byteswap.h0000644000175000017500000000403312652630043013716 00000000000000#ifndef DBALLE_CORE_BYTESWAP_H #define DBALLE_CORE_BYTESWAP_H #include "config.h" #if USE_OWN_BSWAP /* byteswap.h - Byte swapping Copyright (C) 2005, 2007, 2009-2011 Free Software Foundation, Inc. Written by Oskar Liljeblad , 2005. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Given an unsigned 16-bit argument X, return the value corresponding to X with reversed byte order. */ #define bswap_16(x) ((((x) & 0x00FF) << 8) | \ (((x) & 0xFF00) >> 8)) /* Given an unsigned 32-bit argument X, return the value corresponding to X with reversed byte order. */ #define bswap_32(x) ((((x) & 0x000000FF) << 24) | \ (((x) & 0x0000FF00) << 8) | \ (((x) & 0x00FF0000) >> 8) | \ (((x) & 0xFF000000) >> 24)) /* Given an unsigned 64-bit argument X, return the value corresponding to X with reversed byte order. */ #define bswap_64(x) ((((x) & 0x00000000000000FFULL) << 56) | \ (((x) & 0x000000000000FF00ULL) << 40) | \ (((x) & 0x0000000000FF0000ULL) << 24) | \ (((x) & 0x00000000FF000000ULL) << 8) | \ (((x) & 0x000000FF00000000ULL) >> 8) | \ (((x) & 0x0000FF0000000000ULL) >> 24) | \ (((x) & 0x00FF000000000000ULL) >> 40) | \ (((x) & 0xFF00000000000000ULL) >> 56)) #else #include #endif #endif dballe-7.7/dballe/core/file.h0000644000175000017500000000351012652630043012776 00000000000000#ifndef DBA_CORE_FILE_H #define DBA_CORE_FILE_H #include #include #include #include #include namespace dballe { namespace core { /// Base for dballe::File implementations class File : public dballe::File { protected: /// Name of the file std::string m_name; /// FILE structure used to read or write to the file FILE* fd; /// True if fd should be closed on destruction bool close_on_exit; /// Index of the last message read from the file or written to the file int idx; public: File(const std::string& name, FILE* fd, bool close_on_exit=true); virtual ~File(); std::string pathname() const override { return m_name; } bool foreach(std::function dest) override; /** * Resolve the location of a test data file * * This should only be used during dballe unit tests. */ static std::string resolve_test_data_file(const std::string& name); /** * Open a test data file. * * This should only be used during dballe unit tests. */ static std::unique_ptr open_test_data_file(Encoding type, const std::string& name); }; class BufrFile : public dballe::core::File { public: BufrFile(const std::string& name, FILE* fd, bool close_on_exit=true) : File(name, fd, close_on_exit) {} Encoding encoding() const override { return BUFR; } BinaryMessage read() override; void write(const std::string& msg) override; }; class CrexFile : public dballe::core::File { public: CrexFile(const std::string& name, FILE* fd, bool close_on_exit=true) : File(name, fd, close_on_exit) {} Encoding encoding() const override { return CREX; } BinaryMessage read() override; void write(const std::string& msg) override; }; } } #endif dballe-7.7/dballe/core/mkkeydoc0000755000175000017500000002131412652630043013444 00000000000000#!/usr/bin/perl -w use strict; use warnings; # The values are: # required/optional/ignored on insert # required/optional/ignored on query # present/absent on results # comment about the field [optional value] our %comments = ( priority => [ "ignored", "optional", "present", "Every type of report has an associated priority that controls ". "which data are first returned when there is more than one in the ". "same physical space. It can be changed by editing ". "/etc/dballe/repinfo.csv"], priomax => [ "ignored", "optional", "absent" ], priomin => [ "ignored", "optional", "absent" ], rep_memo => [ "required", "optional", "present" ], ana_id => [ "optional", "optional", "present", "Internal DB-ALLe ID referring to a pseudoana entry, used as ". "a shortcut reference instead of specifying the full data" ], block => [ "optional", "optional", "present" ], station => [ "optional", "optional", "present" ], mobile => [ "required", "optional", "present", "Set to 1 if the station is mobile, such as a ship or a flight; else 0"], ident => [ "required if mobile=1", "optional", "present if mobile=1" ], name => [ "optional", "optional", "present" ], lat => [ "required", "optional", "present", "on insert, it has priority over ana_id" ], lon => [ "required", "optional", "present", "on insert, it has priority over ana_id" ], latmax => [ "ignored", "optional", "absent" ], latmin => [ "ignored", "optional", "absent" ], lonmax => [ "ignored", "optional", "absent" ], lonmin => [ "ignored", "optional", "absent" ], height => [ "optional", "optional", "present" ], heightbaro => [ "optional", "optional", "present" ], year_ident => [ "required if mobile=1", "optional", "present if mobile=1", "Only needed when the station is mobile"], month_ident => [ "required if mobile=1", "optional", "present if mobile=1", "Only needed when the station is mobile"], day_ident => [ "required if mobile=1", "optional", "present if mobile=1", "Only needed when the station is mobile"], hour_ident => [ "required if mobile=1", "optional", "present if mobile=1", "Only needed when the station is mobile"], min_ident => [ "required if mobile=1", "optional", "present if mobile=1", "Only needed when the station is mobile"], # datetime => [ "ignored", "ignored", "present", # "Convenience parameter: after a query it contains the datetime informations ", # " all in a single string"], year => [ "required", "optional", "present" ], month => [ "required", "optional", "present" ], day => [ "required", "optional", "present" ], hour => [ "required", "optional", "present" ], min => [ "required", "optional", "present" ], sec => [ "required", "optional", "present" ], yearmax => [ "ignored", "optional", "absent" ], yearmin => [ "ignored", "optional", "absent" ], monthmax => [ "ignored", "optional", "absent" ], monthmin => [ "ignored", "optional", "absent" ], daymax => [ "ignored", "optional", "absent" ], daymin => [ "ignored", "optional", "absent" ], hourmax => [ "ignored", "optional", "absent" ], hourmin => [ "ignored", "optional", "absent" ], minumax => [ "ignored", "optional", "absent" ], minumin => [ "ignored", "optional", "absent" ], secmax => [ "ignored", "optional", "absent" ], secmin => [ "ignored", "optional", "absent" ], leveltype => [ "required", "optional", "present" ], l1 => [ "required", "optional", "present" ], l2 => [ "required", "optional", "present" ], pindicator => [ "required", "optional", "present" ], p1 => [ "required", "optional", "present" ], p2 => [ "required", "optional", "present" ], var => [ "ignored", "optional", "present, indicates the name of the last variable returned" ], varlist => [ "ignored", "optional", "absent", "Comma-separated list of variable codes wanted on output" ], query => [ "ignored", "optional", "absent", "Comma-separated list of query modifiers. Can have one of: ". "'best', 'bigana', 'nosort', 'stream'. ". "Examples: 'best', 'nosort,stream'" ], ana_filter => [ "ignored", "optional", "absent", "Restricts the results to only those stations which ". "have a pseudoana value that matches the filter. ". "Examples: 'height>=1000', 'B02001=1', '1000<=height<=2000" ], data_filter => [ "ignored", "optional", "absent", "Restricts the results to only the variables of the given type, which ". "have a value that matches the filter. ". "Examples: 't<260', 'B22021>2', '10<=B22021<=20'" ], attr_filter => [ "ignored", "optional", "absent", "Restricts the results to only those data which ". "have an attribute that matches the filter. ". "Examples: 'conf>70', 'B33197=0', '25<=conf<=50'" ], limit => [ "ignored", "optional", "absent", "Maximum number of results to return" ], ); my $op = $ARGV[0]; # Read the data my @data; while () { chop(); if (/^([^,]+),([^,]+),(\d+),(\d+),(.+?)\s*$/) { push @data, [$1, $2, $3, $4, $5]; } } our ($tag, $unit, $format, $desc, $ins, $que, $res, $com); our $DoxIntro = q{/**@defgroup dba_record_keywords Keywords used by dba_record @ingroup tables This table lists the keywords used by ::dba_record. You can use them to query and set data using function such as dba_enqi() and dba_seti(). Every keyword is listed together with its measure unit, length in characters or digits and description. \verbatim }; format DoxTop = Name Unit Format Description . format Dox = @<<<<<<<<<<<< @<<<<<<<< @<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $tag, $unit, $format, $desc . our $DoxBottom = q{\endverbatim */ }; our $RstIntro = q{.. table:: Standard parameter names ============= ========= ========== =========================== ========= ======== ========== =============================== Name Unit Format Description On Insert On query On results Comment ============= ========= ========== =========================== ========= ======== ========== =============================== }; format Rst = @<<<<<<<<<<<< @<<<<<<<< ^<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<< ^<<<<<<< ^<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $tag, $unit, $format, $desc, $ins, $que, $res, $com ~~ ^<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<< ^<<<<<<< ^<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $format, $desc, $ins, $que, $res, $com . our $RstBottom = ' ============= ========= ========== =========================== ========= ======== ========== ==============================='; sub mkformat($$$) { my ($unit, $len, $dec) = @_; if ($unit =~ /^CHARACTER|^CODE TABLE/) { return "$len chars"; } elsif ($dec == 0) { return "$len digits"; } else { return '#' x ($len - $dec) . '.' . '#' x $dec; } } if ($op eq 'dox') { print $DoxIntro; $^ = "DoxTop"; $~ = "Dox"; for my $d (@data) { my ($len, $dec); ($tag, $unit, $len, $dec, $desc) = @$d; $com = ($comments{$tag} or ''); $format = mkformat($unit, $len, $dec); write STDOUT; } print $DoxBottom; } elsif ($op eq 'rst') { print $RstIntro; #$^ = "RstTop"; $~ = "Rst"; for my $d (@data) { my ($len, $dec); ($tag, $unit, $len, $dec, $desc) = @$d; $ins = ($comments{$tag}[0] or ''); $que = ($comments{$tag}[1] or ''); $res = ($comments{$tag}[2] or ''); $com = ($comments{$tag}[3] or ''); $format = mkformat($unit, $len, $dec); write STDOUT; } print $RstBottom, "\n"; } elsif ($op eq 'tex') { my $nc = '@{\hspace{0.5mm}}l@{\hspace{0.5mm}}'; my $dsc = '@{\hspace{0.5mm}}p{2.0cm}@{\hspace{0.5mm}}'; my $onc = '@{\hspace{0.5mm}}p{1.4cm}@{\hspace{0.5mm}}'; my $cmc = '@{\hspace{0.5mm}}p{3.5cm}@{\hspace{0.5mm}}'; print qq#{\\begin{scriptsize} \\begin{longtable}{|$nc|$nc|$nc|$dsc|$onc|$onc|$onc|$cmc|} \\hline {\\em Name} & {\\em Unit} & {\\em Format} & {\\em Description} & {\\em On insert input} & {\\em On query input} & {\\em On output} & {\\em Comment} \\\\ \\hline \\endhead \\hline \\endfoot #; for my $d (@data) { my ($len, $dec); ($tag, $unit, $len, $dec, $desc) = @$d; $ins = ($comments{$tag}[0] or ''); $que = ($comments{$tag}[1] or ''); $res = ($comments{$tag}[2] or ''); $com = ($comments{$tag}[3] or ''); $format = mkformat($unit, $len, $dec); $format =~ s/(\#+\.\#+)/{\\tiny $1}/; $unit =~ s/CHARACTER/Character/; $unit =~ s/(NUMERIC|NUMBER)/Numeric/; my $out = join(' & ', ($tag, $unit, $format, $desc, $ins, $que, $res, $com))." \\\\\n"; $out =~ s/(_|#)/\\$1/g; print $out; } print q#\hline \end{longtable} \end{scriptsize} } #; } else { die "unknown output format ".$ARGV[0]; } dballe-7.7/dballe/core/structbuf.cc0000644000175000017500000000354612652630043014247 00000000000000/* * core/structbuf - memory or file-backed storage of structures * * Copyright (C) 2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "structbuf.h" #include #include using namespace std; using namespace wreport; namespace dballe { namespace structbuf { int make_anonymous_tmpfile() { const char* tmpdir = getenv("TMPDIR"); if (!tmpdir) tmpdir = "/tmp"; std::string tmpnam = tmpdir; tmpnam += "/dballe-XXXXXX"; // FIXME: to avoid a string copy, we are writing directly to the string buffer int fd = mkstemp((char*)tmpnam.c_str()); if (fd == -1) error_system::throwf("cannot create temporary file in %s", tmpdir); if (unlink(tmpnam.c_str()) == -1) { int orig_errno = errno; close(fd); throw error_system("cannot remove newly created temporary file", orig_errno); } return fd; } void write_buffer(int fd, void* buf, size_t size) { ssize_t res = ::write(fd, buf, size); if (res == -1) throw error_system("cannot write to temporary file"); if (res < size) throw error_consistency("write to temporary file was interrupted"); } } } dballe-7.7/dballe/core/query.cc0000644000175000017500000005402012652630043013364 00000000000000#include "query.h" #include "var.h" #include "json.h" #include "record.h" #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace core { std::unique_ptr Query::clone() const { return unique_ptr(new Query(*this)); } const Query& Query::downcast(const dballe::Query& query) { const Query* ptr = dynamic_cast(&query); if (!ptr) throw error_consistency("query given is not a core::Query"); return *ptr; } Query& Query::downcast(dballe::Query& query) { Query* ptr = dynamic_cast(&query); if (!ptr) throw error_consistency("query given is not a core::Query"); return *ptr; } unsigned Query::get_modifiers() const { return parse_modifiers(query.c_str()); } void Query::clear() { ana_id = MISSING_INT; prio_min = MISSING_INT; prio_max = MISSING_INT; rep_memo.clear(); mobile = MISSING_INT; ident.clear(); latrange = LatRange(); lonrange = LonRange(); datetime = DatetimeRange(); level = Level(); trange = Trange(); varcodes.clear(); query.clear(); ana_filter.clear(); data_filter.clear(); attr_filter.clear(); limit = MISSING_INT; block = MISSING_INT; station = MISSING_INT; } void Query::set_from_record(const dballe::Record& rec) { const auto& r = core::Record::downcast(rec); want_missing = 0; // Ana ID ana_id = rec.enq("ana_id", MISSING_INT); // Priority int i = rec.enq("priority", MISSING_INT); if (i != MISSING_INT) prio_min = prio_max = i; else { prio_min = rec.enq("priomin", MISSING_INT); prio_max = rec.enq("priomax", MISSING_INT); } // Network rep_memo = rec.enq("rep_memo", ""); // Mobile mobile = rec.enq("mobile", MISSING_INT); // Ident if (const Var* var = rec.get("ident")) ident = var->enqc(); else ident.clear(); // Latitude i = rec.enq("lat", MISSING_INT); if (i != MISSING_INT) latrange.set(i, i); else { int imin = rec.enq("latmin", MISSING_INT); int imax = rec.enq("latmax", MISSING_INT); latrange.set( imin == MISSING_INT ? LatRange::IMIN : imin, imax == MISSING_INT ? LatRange::IMAX : imax); } // Longitude i = rec.enq("lon", MISSING_INT); if (i != MISSING_INT) lonrange.set(i, i); else lonrange.set(rec.enq("lonmin", MISSING_INT), rec.enq("lonmax", MISSING_INT)); // Datetime // fetch all values involved in the computation int ye = rec.enq("year", MISSING_INT); int mo = rec.enq("month", MISSING_INT); int da = rec.enq("day", MISSING_INT); int ho = rec.enq("hour", MISSING_INT); int mi = rec.enq("min", MISSING_INT); int se = rec.enq("sec", MISSING_INT); int yemin = rec.enq("yearmin", MISSING_INT); int momin = rec.enq("monthmin", MISSING_INT); int damin = rec.enq("daymin", MISSING_INT); int homin = rec.enq("hourmin", MISSING_INT); int mimin = rec.enq("minumin", MISSING_INT); int semin = rec.enq("secmin", MISSING_INT); int yemax = rec.enq("yearmax", MISSING_INT); int momax = rec.enq("monthmax", MISSING_INT); int damax = rec.enq("daymax", MISSING_INT); int homax = rec.enq("hourmax", MISSING_INT); int mimax = rec.enq("minumax", MISSING_INT); int semax = rec.enq("secmax", MISSING_INT); // give absolute values priority over ranges if (ye != MISSING_INT) yemin = yemax = ye; if (mo != MISSING_INT) momin = momax = mo; if (da != MISSING_INT) damin = damax = da; if (ho != MISSING_INT) homin = homax = ho; if (mi != MISSING_INT) mimin = mimax = mi; if (se != MISSING_INT) semin = semax = se; datetime = DatetimeRange(yemin, momin, damin, homin, mimin, semin, yemax, momax, damax, homax, mimax, semax); // Level level = r.get_level(); // Trange trange = r.get_trange(); // Varcodes varcodes.clear(); if (const Var* var = rec.get("var")) varcodes.insert(resolve_varcode(var->enq(""))); else if (const Var* var = rec.get("varlist")) resolve_varlist(var->enq(""), varcodes); // Query query = rec.enq("query", ""); // Filters ana_filter = rec.enq("ana_filter", ""); data_filter = rec.enq("data_filter", ""); attr_filter = rec.enq("attr_filter", ""); // Limit limit = rec.enq("limit", MISSING_INT); // WMO block/station block = rec.enq("block", MISSING_INT); station = rec.enq("station", MISSING_INT); } void Query::set_from_test_string(const std::string& s) { if (s.empty()) clear(); else { core::Record rec; rec.set_from_test_string(s); set_from_record(rec); } } namespace { bool removed_or_changed(int val, int other) { // if (val == other) return false; // Not changed // if (val != MISSING_INT && other == MISSING_INT) return false; // Added filter // if (val == MISSING_INT && other != MISSING_INT) return true; // Removed filter // if (val != other) return true; // Changed return !(other == val || other == MISSING_INT); } bool removed_or_changed(const Ident& val, const Ident& other) { return !(other == val || other.is_missing()); } bool removed_or_changed(const std::string& val, const std::string& other) { return !(other == val || other.empty()); } // Return true if sub is a subset of sup, or the same as sup template bool is_subset(const std::set& sub, const std::set& sup) { auto isub = sub.begin(); auto isup = sup.begin(); while (isub != sub.end() && isup != sup.end()) { // A common item: ok. Skip it and continue. if (*isub == *isup) { ++isub; ++isup; continue; } // sub contains an item not in sup: not a subset. if (*isub < *isup) return false; // sup contains an item not in sub: ok. Skip it and continue. ++isup; } // If we have seen all of sub so far, then it is a subset. return isub == sub.end(); } // Return true if sub1--sub2 is contained in sup1--sup2, or is the same bool is_subrange(int sub1, int sub2, int sup1, int sup2) { // If sup is the whole domain, sub is contained in it if (sup1 == MISSING_INT && sup2 == MISSING_INT) return true; // If sup is left-open, only check the right bounds if (sup1 == MISSING_INT) return sub2 != MISSING_INT && sub2 <= sup2; // If sup is right-open, only check the left bounds if (sup2 == MISSING_INT) return sub1 != MISSING_INT && sub1 >= sup1; // sup is bounded both ways if (sub1 == MISSING_INT || sub1 < sup1) return false; if (sub2 == MISSING_INT || sub2 > sup2) return false; return true; } } bool Query::is_subquery(const dballe::Query& other_gen) const { const Query& other = downcast(other_gen); if (removed_or_changed(ana_id, other.ana_id)) return false; if (!is_subrange(prio_min, prio_max, other.prio_min, other.prio_max)) return false; if (removed_or_changed(rep_memo, other.rep_memo)) return false; if (removed_or_changed(mobile, other.mobile)) return false; if (removed_or_changed(ident, other.ident)) return false; if (!other.latrange.contains(latrange)) return false; if (!other.lonrange.contains(lonrange)) return false; if (!other.datetime.contains(datetime)) return false; if (removed_or_changed(level.ltype1, other.level.ltype1)) return false; if (removed_or_changed(level.l1, other.level.l1)) return false; if (removed_or_changed(level.ltype2, other.level.ltype2)) return false; if (removed_or_changed(level.l2, other.level.l2)) return false; if (removed_or_changed(trange.pind, other.trange.pind)) return false; if (removed_or_changed(trange.p1, other.trange.p1)) return false; if (removed_or_changed(trange.p2, other.trange.p2)) return false; // If other.varcodes is a subset, of varcodes, then we just added new // varcodes to the filter if (!is_subset(other.varcodes, varcodes)) return false; // Parse query and check its components unsigned mods = parse_modifiers(query.c_str()); unsigned omods = parse_modifiers(other.query.c_str()); if (mods != omods) { // The only relevant bits is query=best, all the rest we can safely ignore if ((mods & DBA_DB_MODIFIER_BEST) != (omods & DBA_DB_MODIFIER_BEST)) return false; } if (removed_or_changed(ana_filter, other.ana_filter)) return false; if (removed_or_changed(data_filter, other.data_filter)) return false; if (removed_or_changed(attr_filter, other.attr_filter)) return false; // We tolerate limit being changed as long as it has only been reduced if (other.limit != MISSING_INT && (limit == MISSING_INT || limit > other.limit)) return false; if (removed_or_changed(block, other.block)) return false; if (removed_or_changed(station, other.station)) return false; return true; } namespace { struct VarGen { std::function& dest; VarGen(std::function& dest) : dest(dest) {} template void gen(dba_keyword key, const T& val) { Varinfo info = Record::keyword_info(key); dest(Record::keyword_name(key), Var(info, val)); }; void gen(dba_keyword key, const std::string& val) { Varinfo info = Record::keyword_info(key); dest(Record::keyword_name(key), Var(info, val.c_str())); }; void gen(dba_keyword key, const Ident& val) { Varinfo info = Record::keyword_info(key); dest(Record::keyword_name(key), Var(info, val.get())); }; }; } void Query::foreach_key(std::function dest) const { VarGen vargen(dest); if (ana_id != MISSING_INT) vargen.gen(DBA_KEY_ANA_ID, ana_id); if (prio_min != prio_max) { if (prio_min != MISSING_INT) vargen.gen(DBA_KEY_PRIORITY, prio_min); } else { if (prio_min != MISSING_INT) vargen.gen(DBA_KEY_PRIOMIN, prio_min); if (prio_max != MISSING_INT) vargen.gen(DBA_KEY_PRIOMAX, prio_max); } if (!rep_memo.empty()) vargen.gen(DBA_KEY_REP_MEMO, rep_memo); if (mobile != MISSING_INT) vargen.gen(DBA_KEY_MOBILE, mobile); if (!ident.is_missing()) vargen.gen(DBA_KEY_IDENT, ident); if (!latrange.is_missing()) { if (latrange.imin == latrange.imax) vargen.gen(DBA_KEY_LAT, latrange.imin); else { if (latrange.imin != LatRange::IMIN) vargen.gen(DBA_KEY_LATMIN, latrange.imin); if (latrange.imax != LatRange::IMAX) vargen.gen(DBA_KEY_LATMAX, latrange.imax); } } if (!lonrange.is_missing()) { if (lonrange.imin == lonrange.imax) vargen.gen(DBA_KEY_LON, lonrange.imin); else { vargen.gen(DBA_KEY_LONMIN, lonrange.imin); vargen.gen(DBA_KEY_LONMAX, lonrange.imax); } } if (datetime.min == datetime.max) { if (!datetime.min.is_missing()) { vargen.gen(DBA_KEY_YEAR, datetime.min.year); vargen.gen(DBA_KEY_MONTH, datetime.min.month); vargen.gen(DBA_KEY_DAY, datetime.min.day); vargen.gen(DBA_KEY_HOUR, datetime.min.hour); vargen.gen(DBA_KEY_MIN, datetime.min.minute); vargen.gen(DBA_KEY_SEC, datetime.min.second); } } else { if (!datetime.min.is_missing()) { vargen.gen(DBA_KEY_YEARMIN, datetime.min.year); vargen.gen(DBA_KEY_MONTHMIN, datetime.min.month); vargen.gen(DBA_KEY_DAYMIN, datetime.min.day); vargen.gen(DBA_KEY_HOURMIN, datetime.min.hour); vargen.gen(DBA_KEY_MINUMIN, datetime.min.minute); vargen.gen(DBA_KEY_SECMIN, datetime.min.second); } if (!datetime.max.is_missing()) { vargen.gen(DBA_KEY_YEARMAX, datetime.max.year); vargen.gen(DBA_KEY_MONTHMAX, datetime.max.month); vargen.gen(DBA_KEY_DAYMAX, datetime.max.day); vargen.gen(DBA_KEY_HOURMAX, datetime.max.hour); vargen.gen(DBA_KEY_MINUMAX, datetime.max.minute); vargen.gen(DBA_KEY_SECMAX, datetime.max.second); } } if (level.ltype1 != MISSING_INT) vargen.gen(DBA_KEY_LEVELTYPE1, level.ltype1); if (level.l1 != MISSING_INT) vargen.gen(DBA_KEY_L1, level.l1); if (level.ltype2 != MISSING_INT) vargen.gen(DBA_KEY_LEVELTYPE2, level.ltype2); if (level.l2 != MISSING_INT) vargen.gen(DBA_KEY_L2, level.l2); if (trange.pind != MISSING_INT) vargen.gen(DBA_KEY_PINDICATOR, trange.pind); if (trange.p1 != MISSING_INT) vargen.gen(DBA_KEY_P1, trange.p1); if (trange.p2 != MISSING_INT) vargen.gen(DBA_KEY_P2, trange.p2); switch (varcodes.size()) { case 0: break; case 1: vargen.gen(DBA_KEY_VAR, varcode_format(*varcodes.begin())); break; default: { string codes; for (const auto& code: varcodes) { if (codes.empty()) codes = varcode_format(code); else { codes += ","; codes += varcode_format(code); } } vargen.gen(DBA_KEY_VARLIST, codes); break; } } if (!query.empty()) vargen.gen(DBA_KEY_QUERY, query); if (!ana_filter.empty()) vargen.gen(DBA_KEY_ANA_FILTER, ana_filter); if (!data_filter.empty()) vargen.gen(DBA_KEY_DATA_FILTER, data_filter); if (!attr_filter.empty()) vargen.gen(DBA_KEY_ATTR_FILTER, attr_filter); if (limit != MISSING_INT) vargen.gen(DBA_KEY_LIMIT, limit); if (block != MISSING_INT) dest("block", Var(varinfo(WR_VAR(0, 1, 1)), block)); if (station != MISSING_INT) dest("station", Var(varinfo(WR_VAR(0, 1, 2)), station)); } namespace { struct Printer { const Query& q; FILE* out; bool first = true; Printer(const Query& q, FILE* out) : q(q), out(out) {} void print_int(const char* name, int val) { if (val == MISSING_INT) return; if (!first) fputs(", ", out); fprintf(out, "%s=%d", name, val); first = false; } void print_str(const char* name, bool is_present, const std::string& val) { if (!is_present) return; if (!first) fputs(", ", out); fprintf(out, "%s=%s", name, val.c_str()); first = false; } void print_ident(const Ident& val) { if (val.is_missing()) return; if (!first) fputs(", ", out); fprintf(out, "ident=%s", val.get()); first = false; } void print_latrange(const LatRange& latrange) { if (latrange.is_missing()) return; double dmin, dmax; latrange.get(dmin, dmax); if (dmin != LatRange::DMIN) { if (!first) fputs(", ", out); fprintf(out, "latmin=%.5f", dmin); first = false; } if (dmax != LatRange::DMAX) { if (!first) fputs(", ", out); fprintf(out, "latmax=%.5f", dmax); first = false; } } void print_lonrange(const LonRange& lonrange) { if (lonrange.is_missing()) return; double dmin, dmax; lonrange.get(dmin, dmax); if (!first) fputs(", ", out); fprintf(out, "lonmin=%.5f, lonmax=%.5f", dmin, dmax); first = false; } void print_datetimerange(const DatetimeRange& dtr) { if (dtr.is_missing()) return; if (!first) fputs(", ", out); if (dtr.min == dtr.max) fprintf(out, "datetime=%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu", dtr.max.year, dtr.max.month, dtr.max.day, dtr.max.hour, dtr.max.minute, dtr.max.second); else if (dtr.min.is_missing()) fprintf(out, "datetime<=%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu", dtr.max.year, dtr.max.month, dtr.max.day, dtr.max.hour, dtr.max.minute, dtr.max.second); else if (dtr.max.is_missing()) fprintf(out, "datetime>=%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu", dtr.min.year, dtr.min.month, dtr.min.day, dtr.min.hour, dtr.min.minute, dtr.min.second); else fprintf(out, "datetime=%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu to %04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu", dtr.min.year, dtr.min.month, dtr.min.day, dtr.min.hour, dtr.min.minute, dtr.min.second, dtr.max.year, dtr.max.month, dtr.max.day, dtr.max.hour, dtr.max.minute, dtr.max.second); first = false; } void print_level(const char* name, const Level& l) { if (l == Level()) return; if (!first) fputs(", ", out); stringstream buf; buf << l; fprintf(out, "%s=%s", name, buf.str().c_str()); first = false; } void print_trange(const char* name, const Trange& t) { if (t == Trange()) return; if (!first) fputs(", ", out); stringstream buf; buf << t; fprintf(out, "%s=%s", name, buf.str().c_str()); first = false; } void print_varcodes(const char* name, const set& varcodes) { if (varcodes.empty()) return; if (!first) fputs(", ", out); fputs(name, out); putc('=', out); bool lfirst = true; for (const auto& v : varcodes) { if (!lfirst) fputs(",", out); fprintf(out, "%01d%02d%03d", WR_VAR_F(v), WR_VAR_X(v), WR_VAR_Y(v)); lfirst = false; } first = false; } void print() { print_int("ana_id", q.ana_id); print_int("prio_min", q.prio_min); print_int("prio_max", q.prio_max); print_str("rep_memo", !q.rep_memo.empty(), q.rep_memo); print_int("mobile", q.mobile); print_ident(q.ident); print_latrange(q.latrange); print_lonrange(q.lonrange); print_datetimerange(q.datetime); print_level("level", q.level); print_trange("trange", q.trange); print_varcodes("varcodes", q.varcodes); print_str("query", !q.query.empty(), q.query); print_str("ana_filter", !q.ana_filter.empty(), q.ana_filter); print_str("data_filter", !q.data_filter.empty(), q.data_filter); print_str("attr_filter", !q.attr_filter.empty(), q.attr_filter); print_int("limit", q.limit); print_int("block", q.block); print_int("station", q.station); putc('\n', out); } }; } void Query::print(FILE* out) const { Printer printer(*this, out); printer.print(); } void Query::serialize(JSONWriter& out) const { if (ana_id != MISSING_INT) out.add("ana_id", ana_id); if (prio_min != MISSING_INT) out.add("prio_min", prio_min); if (prio_max != MISSING_INT) out.add("prio_max", prio_max); if (!rep_memo.empty()) out.add("rep_memo", rep_memo); if (mobile != MISSING_INT) out.add("mobile", mobile); if (!ident.is_missing()) out.add("ident", ident.get()); if (!latrange.is_missing()) { if (latrange.imin != LatRange::IMIN) out.add("latmin", latrange.imin); if (latrange.imax != LatRange::IMAX) out.add("latmax", latrange.imax); } if (!lonrange.is_missing()) { out.add("lonmin", lonrange.imin); out.add("lonmax", lonrange.imax); } if (datetime.min == datetime.max) { if (!datetime.min.is_missing()) out.add("datetime", datetime.min); } else { if (!datetime.min.is_missing()) out.add("datetime_min", datetime.min); if (!datetime.max.is_missing()) out.add("datetime_max", datetime.max); } if (!level.is_missing()) out.add("level", level); if (!trange.is_missing()) out.add("trange", trange); if (!varcodes.empty()) { out.add("varcodes"); out.add_list(varcodes); } if (!query.empty()) out.add("query", query); if (!ana_filter.empty()) out.add("ana_filter", ana_filter); if (!data_filter.empty()) out.add("data_filter", data_filter); if (!attr_filter.empty()) out.add("attr_filter", attr_filter); if (limit != MISSING_INT) out.add("limit", limit); if (block != MISSING_INT) out.add("block", block); if (station != MISSING_INT) out.add("station", station); } unsigned Query::parse_modifiers(const dballe::Record& rec) { /* Decode query modifiers */ const Var* var = rec.get("query"); if (!var) return 0; if (!var->isset()) return 0; return parse_modifiers(var->enqc()); } unsigned Query::parse_modifiers(const char* s) { unsigned modifiers = 0; while (*s) { size_t len = strcspn(s, ","); int got = 1; switch (len) { case 0: /* If it's an empty token, skip it */ break; case 4: /* "best": if more values exist in a point, get only the best one */ if (strncmp(s, "best", 4) == 0) modifiers |= DBA_DB_MODIFIER_BEST; else got = 0; break; case 6: /* "bigana": optimize with date first */ if (strncmp(s, "bigana", 6) == 0) ; // Not used anymore else if (strncmp(s, "nosort", 6) == 0) modifiers |= DBA_DB_MODIFIER_UNSORTED; else if (strncmp(s, "stream", 6) == 0) ; // Not used anymore else got = 0; break; case 7: if (strncmp(s, "details", 7) == 0) modifiers |= DBA_DB_MODIFIER_SUMMARY_DETAILS; else got = 0; break; default: got = 0; break; } /* Check that we parsed it correctly */ if (!got) error_consistency::throwf("Query modifier \"%.*s\" is not recognized", (int)len, s); /* Move to the next token */ s += len; if (*s == ',') ++s; } return modifiers; } } } dballe-7.7/dballe/core/record.h0000644000175000017500000002247212652630043013345 00000000000000#ifndef DBALLE_CORE_RECORD_H #define DBALLE_CORE_RECORD_H /** @file * @ingroup core * Implement a storage object for a group of related observation data */ #include #include #include #include #include namespace dballe { namespace core { /** * Keyword used to quickly access context and query information from a record. */ enum _dba_keyword { DBA_KEY_ERROR = -1, DBA_KEY_PRIORITY = 0, DBA_KEY_PRIOMAX = 1, DBA_KEY_PRIOMIN = 2, DBA_KEY_REP_MEMO = 3, DBA_KEY_ANA_ID = 4, DBA_KEY_MOBILE = 5, DBA_KEY_IDENT = 6, DBA_KEY_LAT = 7, DBA_KEY_LON = 8, DBA_KEY_LATMAX = 9, DBA_KEY_LATMIN = 10, DBA_KEY_LONMAX = 11, DBA_KEY_LONMIN = 12, DBA_KEY_YEAR = 13, DBA_KEY_MONTH = 14, DBA_KEY_DAY = 15, DBA_KEY_HOUR = 16, DBA_KEY_MIN = 17, DBA_KEY_SEC = 18, DBA_KEY_YEARMAX = 19, DBA_KEY_YEARMIN = 20, DBA_KEY_MONTHMAX = 21, DBA_KEY_MONTHMIN = 22, DBA_KEY_DAYMAX = 23, DBA_KEY_DAYMIN = 24, DBA_KEY_HOURMAX = 25, DBA_KEY_HOURMIN = 26, DBA_KEY_MINUMAX = 27, DBA_KEY_MINUMIN = 28, DBA_KEY_SECMAX = 29, DBA_KEY_SECMIN = 30, DBA_KEY_LEVELTYPE1 = 31, DBA_KEY_L1 = 32, DBA_KEY_LEVELTYPE2 = 33, DBA_KEY_L2 = 34, DBA_KEY_PINDICATOR = 35, DBA_KEY_P1 = 36, DBA_KEY_P2 = 37, DBA_KEY_VAR = 38, DBA_KEY_VARLIST = 39, DBA_KEY_CONTEXT_ID = 40, DBA_KEY_QUERY = 41, DBA_KEY_ANA_FILTER = 42, DBA_KEY_DATA_FILTER = 43, DBA_KEY_ATTR_FILTER = 44, DBA_KEY_LIMIT = 45, DBA_KEY_VAR_RELATED = 46, DBA_KEY_COUNT = 47, }; /** @copydoc ::_dba_keyword */ typedef enum _dba_keyword dba_keyword; std::ostream& operator<<(std::ostream& o, dba_keyword k); /** DB-All.E record. * * A Record is a container for one observation of meteorological values, that * includes anagraphical informations, physical location of the observation in * time and space, and all the observed variables. */ class Record : public dballe::Record { protected: /* The storage for the core keyword data */ wreport::Var* keydata[DBA_KEY_COUNT]; // The variables, sorted by varcode std::vector m_vars; /// Find an item by wreport::Varcode, returning -1 if not found int find_item(wreport::Varcode code) const throw (); /// Find an item by wreport::Varcode, raising an exception if not found wreport::Var& get_item(wreport::Varcode code); /// Find an item by wreport::Varcode, raising an exception if not found const wreport::Var& get_item(wreport::Varcode code) const; /// Remove an item by wreport::Varcode void remove_item(wreport::Varcode code); /** * Look at the value of a parameter * * @return * A const pointer to the internal variable, or NULL if the variable has not * been found. */ const wreport::Var* key_peek(dba_keyword parameter) const throw (); /** * Look at the value of a variable * * @return * A const pointer to the internal variable, or NULL if the variable has not * been found. */ const wreport::Var* var_peek(wreport::Varcode code) const throw (); /** * Remove a parameter from the record. * * @param parameter * The parameter to remove. */ void key_unset(dba_keyword parameter); /** * Remove a parameter from the record. * * @param code * The variable to remove. See @ref vartable.h */ void var_unset(wreport::Varcode code); /// Return the Var for a key, creating it if it is missing wreport::Var& obtain(const char* key); /// Return the Var for a key, creating it if it is missing wreport::Var& obtain(dba_keyword key); /// Return the Var for a variable, creating it if it is missing wreport::Var& obtain(wreport::Varcode code); public: Record(); Record(const Record& rec); ~Record(); std::unique_ptr clone() const override; Record& operator=(const Record& rec); void clear() override; void clear_vars() override; void seti(const char* key, int val) override; void setd(const char* key, double val) override; void setc(const char* key, const char* val) override; void sets(const char* key, const std::string& val) override; void setf(const char* key, const char* val) override; void set_datetime(const Datetime& dt) override; void set_datetimerange(const DatetimeRange& range) override; void set_coords(const Coords& c) override; void set_latrange(const LatRange& lr) override; void set_lonrange(const LonRange& lr) override; void set_level(const Level& lev) override; void set_trange(const Trange& tr) override; void set_var(const wreport::Var& var) override; void set_var_acquire(std::unique_ptr&& var) override; void unset(const char* name) override; const wreport::Var* get(const char* key) const override; void add(const dballe::Record& source) override; bool contains(const dballe::Record& subset) const override; bool equals(const dballe::Record& rec) const override; void foreach_key_ref(std::function dest) const override; void foreach_key_copy(std::function&&)> dest) const override; void print(FILE* out) const override; /** * Return a reference to record downcasted as core::Record. * * Throws an exception if record is not a core::Record. */ static const Record& downcast(const dballe::Record& query); /** * Return a reference to record downcasted as core::Record. * * Throws an exception if record is not a core::Record. */ static Record& downcast(dballe::Record& query); /** * Set the record to contain only those fields that change source1 into source2. * * If a field has been deleted from source1 to source2, it will not be copied * in dest. * * @param source1 * The original record to compute the changes from. * @param source2 * The new record that has changes over source1. */ void set_to_difference(const Record& source1, const Record& source2); /// Compose a Level out of the leveltype1...l2 values Level get_level() const; /// Compose a Trange out of the pindicator...p2 values Trange get_trange() const; /// Compose a Datetime out of the year...sec values Datetime get_datetime() const; /// Compose a DatetimeRange out of the yearmin...secmax values DatetimeRange get_datetimerange() const; /** * Iterate all keys in the record, calling f on them. * * Iteration stops if f returns false. * * The function returns true if it reached the end of the iteration, or * false if it stopped because f returned false. */ bool iter_keys(std::function f) const; /// Return the varcode-sorted vector with the variables const std::vector& vars() const; /** * Set a value in the record according to an assignment encoded in a string. * * String can use keywords, aliases and varcodes. Examples: ana_id=3, * name=Bologna, B12012=32.4 * * In case of numeric parameter, a hyphen ("-") means MISSING_INT (e.g., * `leveltype2=-`). * * @param rec * The record where the value is to be set. * @param str * The string containing the assignment. * @return * The error indicator for the function. */ void set_from_string(const char* str); /** * Set a record from a ", "-separated string of assignments. * * The implementation is not efficient and the method is not safe for any * input, since ", " could appear in a station identifier. It is however * useful to quickly create test queries for unit testing. */ void set_from_test_string(const std::string& s); /** * Encode in a one-liner of comma-separated assignments */ std::string to_string() const; /** * Return the name of a dba_keyword * * @return * The keyword name, or NULL if keyword is not a valid keyword */ static const char* keyword_name(dba_keyword keyword); /** * Return informations about a keyword * * @return * The wreport::Varinfo structure with the informations. */ static wreport::Varinfo keyword_info(dba_keyword keyword); /** * Get the dba_keyword corresponding to the given name * * @returns * The corresponding dba_keyword, or DBA_KEY_ERROR if tag does not match a * valid keyword. */ static dba_keyword keyword_byname(const char* tag); /** * Get the dba_keyword corresponding to the given name * * @param tag * The name to query. * @param len * The length of the name in tag. * @returns * The corresponding dba_keyword, or DBA_KEY_ERROR if tag does not match a * valid keyword. */ static dba_keyword keyword_byname_len(const char* tag, int len); }; struct MatchedRecord : public Matched { const Record& r; MatchedRecord(const Record& r); ~MatchedRecord(); matcher::Result match_var_id(int val) const override; matcher::Result match_station_id(int val) const override; matcher::Result match_station_wmo(int block, int station=-1) const override; matcher::Result match_datetime(const DatetimeRange& range) const override; matcher::Result match_coords(const LatRange& latrange, const LonRange& lonrange) const override; matcher::Result match_rep_memo(const char* memo) const override; }; } } #endif dballe-7.7/dballe/core/mkaliasdoc0000755000175000017500000000322112652630043013742 00000000000000#!/usr/bin/perl -w use strict; use warnings; my $op = $ARGV[0]; # Skip the declaration section while () { last if $_ eq "%%\n"; } # Read the data my @data; my $pos = 0; while () { chop(); last if $_ eq '%%'; my ($name, $val) = split(/,\s*/, $_, 2); $val =~ s/WR_VAR\(0,\s*([0-9]+),\s*([0-9]+)\)/sprintf("B%02d%03d", $1, $2)/e; push @data, [$name, $val]; } @data = sort { $a->[0] cmp $b->[0] } @data; our ($alias, $var); our $DoxIntro = q{/**@defgroup dba_core_aliases Variable aliases @ingroup tables This table lists the aliases that can be used to refer to varcodes. \verbatim }; format DoxTop = Alias Variable . format Dox = @<<<<<<<<<<<< @<<<<< $alias, $var, . our $DoxBottom = q{\endverbatim */ }; if ($op eq 'dox') { print $DoxIntro; $^ = "DoxTop"; $~ = "Dox"; for my $d (@data) { ($alias, $var) = @$d; write STDOUT; } print $DoxBottom; } elsif ($op eq 'tex') { print qq#{\\begin{scriptsize} \\begin{tabular}{|l|l|} \\hline {\\em Alias} & {\\em Variable} \\\\ \\hline #; for my $d (@data) { ($alias, $var) = @$d; $alias =~ s/_/\\_/g; print join(' & ', $alias, $var), "\\\\\n"; } print q#\hline \end{tabular} \end{scriptsize} } #; } elsif ($op eq 'revsolver') { print qq| #include using namespace wreport; namespace dballe { const char* varcode_alias_resolve_reverse(Varcode code) { switch (code) { |; for my $d (@data) { ($alias, $var) = @$d; $var =~ s/B(\d{2})(\d{3})/sprintf("WR_VAR(0, %d, %d)", $1, $2)/e; print "\t\tcase $var: return \"$alias\";\n" } print qq| default: return 0; } } } // namespace dballe |; } else { die "unknown output format ".$ARGV[0]; } dballe-7.7/dballe/core/stlutils-test.cc0000644000175000017500000001030212652630043015052 00000000000000#include "core/tests.h" #include "stlutils.h" using namespace dballe; using namespace dballe::stl; using namespace wreport::tests; using namespace std; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { // Test Intersection add_method("intersection", []() { unique_ptr > sequences(new stl::Sequences); vector a; a.push_back(1); a.push_back(2); a.push_back(3); sequences->add(a); vector b; b.push_back(2); b.push_back(3); sequences->add(b); vector c; c.push_back(0); c.push_back(2); sequences->add(c); Intersection intersection; Intersection::const_iterator i = intersection.begin(sequences); wassert(actual(i != intersection.end()).istrue()); wassert(actual(*i) == 2); ++i; wassert(actual(i == intersection.end()).istrue()); }); // Test Intersection add_method("intersection1", []() { unique_ptr > sequences(new stl::Sequences); vector a; a.push_back(1); sequences->add(a); vector b; b.push_back(1); sequences->add(b); Intersection intersection; Intersection::const_iterator i = intersection.begin(sequences); wassert(actual(i != intersection.end()).istrue()); wassert(actual(*i) == 1); ++i; wassert(actual(i == intersection.end()).istrue()); }); // Test SetIntersection add_method("set_intersection", []() { stl::SetIntersection intersection; set a; a.insert(1); a.insert(2); a.insert(3); intersection.add(a); set b; b.insert(2); b.insert(3); intersection.add(b); set c; c.insert(0); c.insert(2); intersection.add(c); stl::SetIntersection::const_iterator i = intersection.begin(); wassert(actual(i != intersection.end()).istrue()); wassert(actual(*i) == 2); ++i; wassert(actual(i == intersection.end()).istrue()); }); // Test Union add_method("union", []() { unique_ptr > sequences(new stl::Sequences); vector a; sequences->add(a); vector b; sequences->add(b); Union ab; Union::const_iterator i = ab.begin(sequences); wassert(actual(i == ab.end()).istrue()); }); // Test Union add_method("union1", []() { unique_ptr > sequences(new stl::Sequences); vector a; a.push_back(1); sequences->add(a); vector b; sequences->add(b); Union ab; Union::const_iterator i = ab.begin(sequences); wassert(actual(i != ab.end()).istrue()); wassert(actual(*i) == 1); ++i; wassert(actual(i == ab.end()).istrue()); }); // Test Union add_method("union2", []() { unique_ptr > sequences(new stl::Sequences); vector a; a.push_back(1); a.push_back(2); sequences->add(a); vector b; b.push_back(2); b.push_back(3); sequences->add(b); Union ab; Union::const_iterator i = ab.begin(sequences); wassert(actual(i != ab.end()).istrue()); wassert(actual(*i) == 1); ++i; wassert(actual(i != ab.end()).istrue()); wassert(actual(*i) == 2); ++i; wassert(actual(i != ab.end()).istrue()); wassert(actual(*i) == 3); ++i; wassert(actual(i == ab.end()).istrue()); }); } } test("core_stlutils"); } #include "stlutils.tcc" dballe-7.7/dballe/core/file-test.cc0000644000175000017500000000047712652630043014122 00000000000000#include "core/tests.h" #include "core/file.h" using namespace dballe; using namespace dballe::tests; using namespace std; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("empty", []() { }); } } test("core_file"); } dballe-7.7/dballe/core/aliases-reverse.cc0000644000175000017500000000240112652630120015301 00000000000000 #include using namespace wreport; namespace dballe { const char* varcode_alias_resolve_reverse(Varcode code) { switch (code) { case WR_VAR(0, 1, 1): return "block"; case WR_VAR(0, 33, 7): return "conf"; case WR_VAR(0, 33, 195): return "data_id"; case WR_VAR(0, 7, 30): return "height"; case WR_VAR(0, 7, 31): return "heightbaro"; case WR_VAR(0, 10, 51): return "mslp"; case WR_VAR(0, 22, 1): return "mwd"; case WR_VAR(0, 22, 74): return "mwp"; case WR_VAR(0, 1, 19): return "name"; case WR_VAR(0, 15, 192): return "no"; case WR_VAR(0, 15, 193): return "no2"; case WR_VAR(0, 15, 194): return "o3"; case WR_VAR(0, 10, 4): return "p"; case WR_VAR(0, 15, 195): return "pm10"; case WR_VAR(0, 22, 71): return "pp1d"; case WR_VAR(0, 13, 1): return "q"; case WR_VAR(0, 13, 3): return "rh"; case WR_VAR(0, 1, 2): return "station"; case WR_VAR(0, 22, 70): return "swh"; case WR_VAR(0, 12, 101): return "t"; case WR_VAR(0, 12, 103): return "td"; case WR_VAR(0, 12, 11): return "tmax"; case WR_VAR(0, 12, 12): return "tmin"; case WR_VAR(0, 13, 11): return "tp"; case WR_VAR(0, 11, 3): return "u"; case WR_VAR(0, 11, 4): return "v"; case WR_VAR(0, 10, 3): return "z"; default: return 0; } } } // namespace dballe dballe-7.7/dballe/core/stlutils.h0000644000175000017500000002353212652630043013750 00000000000000/* * core/stlutils - Useful functions to work with the STL * * Copyright (C) 2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBA_CORE_STLUTILS_H #define DBA_CORE_STLUTILS_H #include #include #include namespace dballe { namespace stl { namespace stlutils { template struct Sequence { virtual ~Sequence() {} virtual bool valid() const = 0; virtual const T& get() const = 0; virtual void next() = 0; }; } // back to dballe::stl /// List of ranges template struct Sequences : public std::vector*> { typedef typename std::vector*>::iterator iterator; typedef typename std::vector*>::const_iterator const_iterator; Sequences() {} ~Sequences() { for (iterator i = this->begin(); i != this->end(); ++i) delete *i; } /// Add a singleton set void add_singleton(const T& val); // Add a begin-end range template void add(const ITER& begin, const ITER& end); // Add a container's begin()-end() range template void add(const C& container); void add(std::unique_ptr< stlutils::Sequence >& sequence); // Add the union of the given sequences void add_union(std::unique_ptr< Sequences >& sequences); // Add the union of the given sequences void add_intersection(std::unique_ptr< Sequences >& sequences); private: Sequences(const Sequences&); Sequences& operator=(const Sequences&); }; namespace stlutils { template struct SequenceGenerator { Sequences* sequences; SequenceGenerator() : sequences(0) {} SequenceGenerator(const SequenceGenerator& sg) : sequences(sg.sequences) { // unique_ptr semantics const_cast*>(&sg)->sequences = 0; } SequenceGenerator(std::unique_ptr< Sequences >& sequences) : sequences(sequences.release()) {} ~SequenceGenerator() { if (sequences) delete sequences; } SequenceGenerator& operator=(const SequenceGenerator& sg) { // unique_ptr semantics if (&sg == this) return this; if (sequences) delete sequences; sequences = sg.sequences; const_cast*>(&sg)->sequences = 0; return *this; } void clear() { if (sequences) delete sequences; sequences = 0; } bool has_items() const { return sequences != 0; } bool operator==(const SequenceGenerator& i) const { if (sequences == i.sequences) return true; if (!sequences || !i.sequences) return false; return *sequences == *i.sequences; } bool operator!=(const SequenceGenerator& i) const { if (sequences == i.sequences) return false; if (!sequences || !i.sequences) return true; return *sequences != *i.sequences; } }; template struct Itersection : public SequenceGenerator, public std::iterator { Itersection() {} Itersection(const Itersection& sg) : SequenceGenerator(sg) {} Itersection(std::unique_ptr< Sequences >& sequences) : SequenceGenerator(sequences) { sync_iters(); } const T& get() const { return (*this->sequences)[0]->get(); } void advance() { (*this->sequences)[0]->next(); sync_iters(); } // Advance iterators so that they all point to items of the same value, // or so that we become the end iterator void sync_iters(); const T& operator*() const { return this->get(); } Itersection& operator++() { this->advance(); return *this; } }; template struct Iterunion : public SequenceGenerator, public std::iterator { const T* minval; Iterunion() {} Iterunion(const Iterunion& sg) : SequenceGenerator(sg), minval(sg.minval) { // unique_ptr semantics const_cast*>(&sg)->minval = 0; } Iterunion(std::unique_ptr< Sequences >& sequences) : SequenceGenerator(sequences), minval(0) { find_min(); } Iterunion& operator=(const Iterunion& sg) { // unique_ptr semantics SequenceGenerator::operator=(sg); minval = sg.minval; const_cast*>(&sg)->minval = 0; return *this; } const T& get() const { return *minval; } /** * Find the next minimum value. * * If minval is 0, set it to the minimum value. * If minval points to an element, advance all sequences that have that * element as minimum value, and set minval to the next minimum value. * * Returns false when all sequences are exausted; true if a new minimum * value was found. */ void find_min(); const T& operator*() const { return this->get(); } Iterunion& operator++() { this->find_min(); return *this; } }; } /** * Virtual container containing the intersection of an arbitrary number of * sorted (begin, end) sequences. */ template class Intersection { public: typedef stlutils::Itersection const_iterator; const_iterator begin(std::unique_ptr< Sequences >& sequences) const { return const_iterator(sequences); } const_iterator end() const { return const_iterator(); } }; template class SetIntersection { protected: std::vector*> sets; Intersection intersection; public: void add(const std::set& set) { sets.push_back(&set); } typedef typename Intersection::const_iterator const_iterator; const_iterator begin() { std::unique_ptr< Sequences > sequences(new Sequences); // Look for the highest first element in all sets bool first = true; T max_of_first; for (typename std::vector*>::const_iterator i = sets.begin(); i != sets.end(); ++i) { const std::set& s = **i; // If one of the sets is empty, then the intersection is empty if (s.begin() == s.end()) return end(); if (first) { max_of_first = *s.begin(); first = false; } else { if (max_of_first < *s.begin()) max_of_first = *s.begin(); } } // Populate intersection with all the ranges we intersect for (typename std::vector*>::const_iterator i = sets.begin(); i != sets.end(); ++i) { const std::set& s = **i; sequences->add(s.lower_bound(max_of_first), s.end()); } return intersection.begin(sequences); } const_iterator end() { return intersection.end(); } }; /** * Virtual container containing the union of an arbitrary number of * sorted (begin, end) sequences. */ template class Union { public: typedef stlutils::Iterunion const_iterator; const_iterator begin(std::unique_ptr< Sequences >& sequences) const { return const_iterator(sequences); } const_iterator end() const { return const_iterator(); } }; /** * Similar to std::inserter, but just calls target.insert() without requiring * it to have iterators at all. */ template class TrivialInserter : public std::iterator { protected: T* target; public: TrivialInserter(T& target) : target(&target) {} template V operator=(V val) { target->insert(val); return val; } TrivialInserter& operator*() { return *this; } TrivialInserter& operator++() { return *this; } TrivialInserter& operator++(int) { return *this; } }; template TrivialInserter trivial_inserter(T& target) { return TrivialInserter(target); } /** * Similar to std::inserter, but just calls target.insert() without requiring * it to have iterators at all. */ template class Pusher : public std::iterator { protected: T* target; public: Pusher(T& target) : target(&target) {} template V operator=(V val) { target->push(val); return val; } Pusher& operator*() { return *this; } Pusher& operator++() { return *this; } Pusher& operator++(int) { return *this; } }; template Pusher pusher(T& target) { return Pusher(target); } /** * Similar to std::inserter, but just calls target.insert() without requiring * it to have iterators at all. */ template class Eraser : public std::iterator { protected: T* target; public: Eraser(T& target) : target(&target) {} template V operator=(V val) { target->erase(val); return val; } Eraser& operator*() { return *this; } Eraser& operator++() { return *this; } Eraser& operator++(int) { return *this; } }; template Eraser eraser(T& target) { return Eraser(target); } } } #endif dballe-7.7/dballe/core/match-wreport.h0000644000175000017500000000364512652630043014664 00000000000000#ifndef DBALLE_CORE_MATCH_WREPORT_H #define DBALLE_CORE_MATCH_WREPORT_H /** @file * @ingroup core * Implement a storage object for a group of related observation data */ #include namespace wreport { struct Var; struct Subset; struct Bulletin; } namespace dballe { struct MatchedSubset : public Matched { const wreport::Subset& r; MatchedSubset(const wreport::Subset& r); ~MatchedSubset(); /** * Return YES if the subset contains at least one var with the given B33195 * attribute; else return NA. */ matcher::Result match_var_id(int val) const override; matcher::Result match_station_id(int val) const override; matcher::Result match_station_wmo(int block, int station=-1) const override; matcher::Result match_datetime(const DatetimeRange& range) const override; matcher::Result match_coords(const LatRange& latrange, const LonRange& lonrange) const override; matcher::Result match_rep_memo(const char* memo) const override; protected: Datetime date; int lat, lon; const wreport::Var* var_ana_id; const wreport::Var* var_block; const wreport::Var* var_station; const wreport::Var* var_rep_memo; }; /** * Match all subsets in turn, returning true if at least one subset matches */ struct MatchedBulletin : public Matched { const wreport::Bulletin& r; MatchedBulletin(const wreport::Bulletin& r); ~MatchedBulletin(); matcher::Result match_var_id(int val) const override; matcher::Result match_station_id(int val) const override; matcher::Result match_station_wmo(int block, int station=-1) const override; matcher::Result match_datetime(const DatetimeRange& range) const override; matcher::Result match_coords(const LatRange& latrange, const LonRange& lonrange) const override; matcher::Result match_rep_memo(const char* memo) const override; protected: const MatchedSubset** subsets; }; } #endif dballe-7.7/dballe/core/record_keyword.gperf0000644000175000017500000002150012652630043015754 00000000000000%define slot-name tag %define class-name RecordKeywords %define lookup-function-name find %struct-type %language=C++ %global-table %compare-strncmp /* Using %switch may be faster (remember to check when doing optimizations) */ %{ #include #include #include "dballe/var.h" #include "dballe/core/record.h" using namespace wreport; namespace dballe { namespace core { %} struct tagdef { const char* tag; dba_keyword index; }; %% priority, DBA_KEY_PRIORITY priomax, DBA_KEY_PRIOMAX priomin, DBA_KEY_PRIOMIN rep_memo, DBA_KEY_REP_MEMO ana_id, DBA_KEY_ANA_ID mobile, DBA_KEY_MOBILE ident, DBA_KEY_IDENT lat, DBA_KEY_LAT lon, DBA_KEY_LON latmax, DBA_KEY_LATMAX latmin, DBA_KEY_LATMIN lonmax, DBA_KEY_LONMAX lonmin, DBA_KEY_LONMIN year, DBA_KEY_YEAR month, DBA_KEY_MONTH day, DBA_KEY_DAY hour, DBA_KEY_HOUR min, DBA_KEY_MIN sec, DBA_KEY_SEC yearmax, DBA_KEY_YEARMAX yearmin, DBA_KEY_YEARMIN monthmax, DBA_KEY_MONTHMAX monthmin, DBA_KEY_MONTHMIN daymax, DBA_KEY_DAYMAX daymin, DBA_KEY_DAYMIN hourmax, DBA_KEY_HOURMAX hourmin, DBA_KEY_HOURMIN minumax, DBA_KEY_MINUMAX minumin, DBA_KEY_MINUMIN secmax, DBA_KEY_SECMAX secmin, DBA_KEY_SECMIN leveltype1, DBA_KEY_LEVELTYPE1 l1, DBA_KEY_L1 leveltype2, DBA_KEY_LEVELTYPE2 l2, DBA_KEY_L2 pindicator, DBA_KEY_PINDICATOR p1, DBA_KEY_P1 p2, DBA_KEY_P2 var, DBA_KEY_VAR varlist, DBA_KEY_VARLIST context_id, DBA_KEY_CONTEXT_ID query, DBA_KEY_QUERY ana_filter, DBA_KEY_ANA_FILTER data_filter, DBA_KEY_DATA_FILTER attr_filter, DBA_KEY_ATTR_FILTER limit, DBA_KEY_LIMIT var_related, DBA_KEY_VAR_RELATED %% #define DEF_MAXINT 0, 10, 0, 31 #define DEF_INT(digits) 0, digits, 0, digits*8 namespace { struct keyword_infos { struct _Varinfo infos[DBA_KEY_COUNT]; keyword_infos() { infos[DBA_KEY_PRIORITY ].set_bufr (0, "Priority of this type of report", "NUMBER", DEF_MAXINT); infos[DBA_KEY_PRIOMAX ].set_bufr (0, "Maximum priority of reports queried", "NUMBER", DEF_MAXINT); infos[DBA_KEY_PRIOMIN ].set_bufr (0, "Minimum priority of reports queried", "NUMBER", DEF_MAXINT); infos[DBA_KEY_REP_MEMO ].set_string(0, "Mnemonic alias for type of report", 20); infos[DBA_KEY_ANA_ID ].set_bufr (0, "Station database ID", "NUMERIC", DEF_MAXINT); infos[DBA_KEY_MOBILE ].set_bufr (0, "Station is mobile", "NUMERIC", DEF_MAXINT); infos[DBA_KEY_IDENT ].set_string(0, "Identifier of flight or ship", 64); infos[DBA_KEY_LAT ].set_bufr (0, "Latitude", "DEGREE", 5, 7, -9000000, 25); infos[DBA_KEY_LON ].set_bufr (0, "Longitude", "DEGREE", 5, 8, -18000000, 26); infos[DBA_KEY_LATMAX ].set_bufr (0, "Maximum latitude queried", "DEGREE", 5, 7, -9000000, 25); infos[DBA_KEY_LATMIN ].set_bufr (0, "Minimum latitude queried", "DEGREE", 5, 7, -9000000, 25); infos[DBA_KEY_LONMAX ].set_bufr (0, "Maximum longitude queried", "DEGREE", 5, 8, -18000000, 26); infos[DBA_KEY_LONMIN ].set_bufr (0, "Minimum longitude queried", "DEGREE", 5, 8, -18000000, 26); infos[DBA_KEY_YEAR ].set_bufr (0, "Year", "YEAR", DEF_INT(4)); infos[DBA_KEY_MONTH ].set_bufr (0, "Month", "MONTH", DEF_INT(2)); infos[DBA_KEY_DAY ].set_bufr (0, "Day", "DAY", DEF_INT(2)); infos[DBA_KEY_HOUR ].set_bufr (0, "Hour", "HOUR", DEF_INT(2)); infos[DBA_KEY_MIN ].set_bufr (0, "Minutes", "MINUTE", DEF_INT(2)); infos[DBA_KEY_SEC ].set_bufr (0, "Seconds", "SECOND", DEF_INT(2)); infos[DBA_KEY_YEARMAX ].set_bufr (0, "Maximum year queried", "YEAR", DEF_INT(4)); infos[DBA_KEY_YEARMIN ].set_bufr (0, "Year or minimum year queried", "YEAR", DEF_INT(4)); infos[DBA_KEY_MONTHMAX ].set_bufr (0, "Maximum month queried", "MONTH", DEF_INT(2)); infos[DBA_KEY_MONTHMIN ].set_bufr (0, "Minimum month queried", "MONTH", DEF_INT(2)); infos[DBA_KEY_DAYMAX ].set_bufr (0, "Maximum day queried", "DAY", DEF_INT(2)); infos[DBA_KEY_DAYMIN ].set_bufr (0, "Minimum day queried", "DAY", DEF_INT(2)); infos[DBA_KEY_HOURMAX ].set_bufr (0, "Maximum hour queried", "HOUR", DEF_INT(2)); infos[DBA_KEY_HOURMIN ].set_bufr (0, "Minumum hour queried", "HOUR", DEF_INT(2)); infos[DBA_KEY_MINUMAX ].set_bufr (0, "Maxminum minutes queried", "MINUTE", DEF_INT(2)); infos[DBA_KEY_MINUMIN ].set_bufr (0, "Minimum minutes queried", "MINUTE", DEF_INT(2)); infos[DBA_KEY_SECMAX ].set_bufr (0, "Maxminum seconds queried", "SECOND", DEF_INT(2)); infos[DBA_KEY_SECMIN ].set_bufr (0, "Minimum seconds queried", "SECOND", DEF_INT(2)); infos[DBA_KEY_LEVELTYPE1 ].set_bufr (0, "Type of first level", "NUMBER", DEF_MAXINT); infos[DBA_KEY_L1 ].set_bufr (0, "Level layer L1", "NUMBER", DEF_MAXINT); infos[DBA_KEY_LEVELTYPE2 ].set_bufr (0, "Type of second level", "NUMBER", DEF_MAXINT); infos[DBA_KEY_L2 ].set_bufr (0, "Level layer L2", "NUMBER", DEF_MAXINT); infos[DBA_KEY_PINDICATOR ].set_bufr (0, "P indicator for time range", "NUMBER", DEF_MAXINT); infos[DBA_KEY_P1 ].set_bufr (0, "Time range P1", "SECOND", DEF_MAXINT); infos[DBA_KEY_P2 ].set_bufr (0, "Time range P2", "SECOND", DEF_MAXINT); infos[DBA_KEY_VAR ].set_string(0, "Variable queried", 7); infos[DBA_KEY_VARLIST ].set_string(0, "List of variables to query", 255); infos[DBA_KEY_CONTEXT_ID ].set_bufr (0, "Context ID of the variable", "NUMERIC", DEF_MAXINT); infos[DBA_KEY_QUERY ].set_string(0, "Query behaviour modifier", 255); infos[DBA_KEY_ANA_FILTER ].set_string(0, "Filter on anagraphical data", 255); infos[DBA_KEY_DATA_FILTER].set_string(0, "Filter on data", 255); infos[DBA_KEY_ATTR_FILTER].set_string(0, "Filter on data attributes", 255); infos[DBA_KEY_LIMIT ].set_bufr (0, "Maximum number of results to return", "NUMBER", DEF_MAXINT); infos[DBA_KEY_VAR_RELATED].set_string(0, "Variable related to attribute queried", 6); } }; static struct keyword_infos* infos = NULL; } static const char* keyword_names[] = { "priority", "priomax", "priomin", "rep_memo", "ana_id", "mobile", "ident", "lat", "lon", "latmax", "latmin", "lonmax", "lonmin", "year", "month", "day", "hour", "min", "sec", "yearmax", "yearmin", "monthmax", "monthmin", "daymax", "daymin", "hourmax", "hourmin", "minumax", "minumin", "secmax", "secmin", "leveltype1", "l1", "leveltype2", "l2", "pindicator", "p1", "p2", "var", "varlist", "context_id", "query", "ana_filter", "data_filter", "attr_filter", "limit", "var_related", }; const char* Record::keyword_name(dba_keyword key) { return keyword_names[key]; } Varinfo Record::keyword_info(dba_keyword keyword) { if (infos == NULL) infos = new keyword_infos; return &(infos->infos[keyword]); } dba_keyword Record::keyword_byname(const char* tag) { struct tagdef* res = RecordKeywords::find(tag, strlen(tag)); if (res == NULL) return DBA_KEY_ERROR; else return res->index; } dba_keyword Record::keyword_byname_len(const char* tag, int len) { struct tagdef* res = RecordKeywords::find(tag, len); if (res == NULL) return DBA_KEY_ERROR; else return res->index; } /* dba_err dba_record_keyword_selftest() { dba_keyword i, j; for (i = 0; i < DBA_KEY_COUNT; i++) { if (wordlist[i + 1].index != i) return dba_error_consistency("wordlist entry %d has index %d that does not match the position", i, wordlist[i + 1].index); j = dba_record_keyword_byname(wordlist[i + 1].tag); if (j != i) return dba_error_consistency("hashing of entry '%s' did not give expected index %d", wordlist[i + 1].tag, i); } return dba_error_ok(); } */ } } dballe-7.7/dballe/core/tests.cc0000644000175000017500000002361412652630043013366 00000000000000#include "tests.h" #include "record.h" #include "matcher.h" #include #include #include #include #include using namespace wreport; using namespace dballe::tests; using namespace std; namespace dballe { namespace tests { static std::string tag; bool test_can_run(const std::string& group_name, const std::string& test_name) { const char* filter = getenv("FILTER"); const char* except = getenv("EXCEPT"); if (!filter && !except) return true; if (filter && fnmatch(filter, group_name.c_str(), 0) == FNM_NOMATCH) return false; if (!except || fnmatch(except, group_name.c_str(), 0) == FNM_NOMATCH) return true; return false; } /* static void _ensureRecordHas(const char* file, int line, dba_record rec, const char* key, int val) { int v; INNER_CHECKED(dba_enqi(rec, key, &v)); ensure_equals(v, val); } static void _ensureRecordHas(const char* file, int line, dba_record rec, const char* key, double val) { double v; INNER_CHECKED(dba_enqd(rec, key, &v)); ensure_equals(v, val); } static void _ensureRecordHas(const char* file, int line, dba_record rec, const char* key, const char* val) { const char* v; INNER_CHECKED(dba_enqc(rec, key, &v)); gen_ensure(strcmp(v, val) == 0); } #define ensureRecordHas(...) _ensureRecordHas(__FILE__, __LINE__, __VA_ARGS__) */ const static Varcode generator_varcodes[] = { WR_VAR(0, 1, 1), WR_VAR(0, 1, 2), WR_VAR(0, 1, 8), WR_VAR(0, 1, 11), WR_VAR(0, 1, 12), WR_VAR(0, 1, 13), WR_VAR(0, 2, 1), WR_VAR(0, 2, 2), WR_VAR(0, 2, 5), WR_VAR(0, 2, 11), WR_VAR(0, 2, 12), WR_VAR(0, 2, 61), WR_VAR(0, 2, 62), WR_VAR(0, 2, 63), WR_VAR(0, 2, 70), WR_VAR(0, 4, 1), WR_VAR(0, 4, 2), WR_VAR(0, 4, 3), WR_VAR(0, 4, 4), WR_VAR(0, 4, 5), WR_VAR(0, 5, 1), WR_VAR(0, 6, 1), WR_VAR(0, 7, 30), WR_VAR(0, 7, 2), WR_VAR(0, 7, 31), WR_VAR(0, 8, 1), WR_VAR(0, 8, 4), WR_VAR(0, 8, 21), WR_VAR(0, 10, 3), WR_VAR(0, 10, 4), WR_VAR(0, 10, 51), WR_VAR(0, 10, 61), WR_VAR(0, 10, 63), WR_VAR(0, 10, 197), WR_VAR(0, 11, 1), WR_VAR(0, 11, 2), WR_VAR(0, 11, 3), WR_VAR(0, 11, 4), }; #if 0 generator::~generator() { for (std::vector::iterator i = reused_pseudoana_fixed.begin(); i != reused_pseudoana_fixed.end(); i++) dba_record_delete(*i); for (std::vector::iterator i = reused_pseudoana_mobile.begin(); i != reused_pseudoana_mobile.end(); i++) dba_record_delete(*i); for (std::vector::iterator i = reused_context.begin(); i != reused_context.end(); i++) dba_record_delete(*i); } dba_err generator::fill_pseudoana(dba_record rec, bool mobile) { dba_record ana; if ((mobile && reused_pseudoana_mobile.empty()) || (!mobile && reused_pseudoana_fixed.empty()) || rnd(0.3)) { DBA_RUN_OR_RETURN(dba_record_create(&ana)); /* Pseudoana */ DBA_RUN_OR_RETURN(dba_record_key_setd(ana, DBA_KEY_LAT, rnd(-90, 90))); DBA_RUN_OR_RETURN(dba_record_key_setd(ana, DBA_KEY_LON, rnd(-180, 180))); if (mobile) { DBA_RUN_OR_RETURN(dba_record_key_setc(ana, DBA_KEY_IDENT, rnd(10).c_str())); DBA_RUN_OR_RETURN(dba_record_key_seti(ana, DBA_KEY_MOBILE, 1)); reused_pseudoana_mobile.push_back(ana); } else { //DBA_RUN_OR_RETURN(dba_record_key_seti(ana, DBA_KEY_BLOCK, rnd(0, 99))); //DBA_RUN_OR_RETURN(dba_record_key_seti(ana, DBA_KEY_STATION, rnd(0, 999))); DBA_RUN_OR_RETURN(dba_record_key_seti(ana, DBA_KEY_MOBILE, 0)); reused_pseudoana_fixed.push_back(ana); } } else { if (mobile) ana = reused_pseudoana_mobile[rnd(0, reused_pseudoana_mobile.size() - 1)]; else ana = reused_pseudoana_fixed[rnd(0, reused_pseudoana_fixed.size() - 1)]; } DBA_RUN_OR_RETURN(dba_record_add(rec, ana)); return dba_error_ok(); } dba_err generator::fill_context(dba_record rec) { dba_record ctx; if (reused_context.empty() || rnd(0.7)) { DBA_RUN_OR_RETURN(dba_record_create(&ctx)); /* Context */ DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_YEAR, rnd(2002, 2005))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_MONTH, rnd(1, 12))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_DAY, rnd(1, 28))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_HOUR, rnd(0, 23))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_MIN, rnd(0, 59))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_LEVELTYPE1, rnd(0, 300))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_L1, rnd(0, 100000))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_LEVELTYPE2, rnd(0, 300))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_L2, rnd(0, 100000))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_PINDICATOR, rnd(0, 300))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_P1, rnd(0, 100000))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_P2, rnd(0, 100000))); DBA_RUN_OR_RETURN(dba_record_key_seti(ctx, DBA_KEY_REP_COD, rnd(105, 149))); reused_context.push_back(ctx); } else { ctx = reused_context[rnd(0, reused_context.size() - 1)]; } DBA_RUN_OR_RETURN(dba_record_add(rec, ctx)); return dba_error_ok(); } dba_err generator::fill_record(dba_record rec) { DBA_RUN_OR_RETURN(fill_pseudoana(rec, rnd(0.8))); DBA_RUN_OR_RETURN(fill_context(rec)); DBA_RUN_OR_RETURN(dba_record_var_setc(rec, generator_varcodes[rnd(0, sizeof(generator_varcodes) / sizeof(dba_varcode))], "1")); return dba_error_ok(); } #endif #if 0 dba_err read_file(dba_encoding type, const std::string& name, dba_raw_consumer& cons) { dba_err err = DBA_OK; dba_file file = open_test_data(name.c_str(), type); dba_rawmsg raw = 0; int found; DBA_RUN_OR_GOTO(cleanup, dba_rawmsg_create(&raw)); DBA_RUN_OR_GOTO(cleanup, dba_file_read(file, raw, &found)); while (found) { DBA_RUN_OR_GOTO(cleanup, cons.consume(raw)); DBA_RUN_OR_GOTO(cleanup, dba_file_read(file, raw, &found)); } cleanup: if (file) dba_file_delete(file); if (raw) dba_rawmsg_delete(raw); return err == DBA_OK ? dba_error_ok() : err; } #endif std::string datafile(const std::string& fname) { // Skip appending the test data path for pathnames starting with ./ if (fname[0] == '.') return fname; const char* testdatadirenv = getenv("DBA_TESTDATA"); std::string testdatadir = testdatadirenv ? testdatadirenv : "."; return testdatadir + "/" + fname; } unique_ptr open_test_data(const char* filename, File::Encoding type) { return unique_ptr(File::create(type, datafile(filename), "r")); } BinaryMessage read_rawmsg(const char* filename, File::Encoding type) { unique_ptr f = wcallchecked(open_test_data(filename, type)); BinaryMessage res = f->read(); wassert(actual(res).istrue()); return res; } #if 0 void vars_equal(const Record& expected) { return TestRecordVarsEqual(this->actual, expected); } void TestRecordValEqual::check() const { const wreport::Var* evar = expected.get(name); const wreport::Var* avar = actual.get(name); if (with_missing_int && evar && evar->enq(MISSING_INT) == MISSING_INT) evar = NULL; if (with_missing_int && avar && avar->enq(MISSING_INT) == MISSING_INT) avar = NULL; if (!evar && !avar) return; if (!evar || !avar || evar->code() != avar->code() || !evar->value_equals(*avar)) { std::stringstream ss; ss << "records differ on " << name << ": "; if (!evar) ss << "it is expected unset"; else ss << evar->format() << " is expected"; ss << ", but actual "; if (!avar) ss << "is unset"; else ss << "has " << avar->format(); throw TestFailed(ss.str()); } } #endif void ActualRecord::vars_equal(const Values& expected) const { WREPORT_TEST_INFO(locinfo); const auto& act = core::Record::downcast(_actual); locinfo() << "Expected: " /* << expected.to_string() */ << " actual: " << act.to_string(); const vector& vars1 = act.vars(); vector vars2; for (const auto& i : expected) vars2.push_back(i.second.var); if (vars1.size() != vars2.size()) { std::stringstream ss; ss << "records have a different number of variables. Expected is " << vars2.size() << " and actual has " << vars1.size(); throw TestFailed(ss.str()); } for (unsigned i = 0; i < vars1.size(); ++i) { if (*vars1[i] != *vars2[i]) { std::stringstream ss; ss << "records variables differ at position " << i << ": expected is " << varcode_format(vars2[i]->code()) << "=" << vars2[i]->format("") << " and actual has " << varcode_format(vars1[i]->code()) << "=" << vars1[i]->format(""); throw TestFailed(ss.str()); } } } void set_record_from_string(Record& rec, const std::string& s) { auto& r = core::Record::downcast(rec); str::Split split(s, ", "); for (const auto& i: split) r.set_from_string(i.c_str()); } unique_ptr record_from_string(const std::string& s) { auto res = Record::create(); set_record_from_string(*res, s); return move(res); } unique_ptr query_from_string(const std::string& s) { core::Query* q; unique_ptr res(q = new core::Query); q->set_from_test_string(s); return res; } core::Query core_query_from_string(const std::string& s) { core::Query q; q.set_from_test_string(s); return q; } void ActualMatcherResult::operator==(int expected) const { if (expected == _actual) return; std::stringstream ss; ss << "actual match result is " << matcher::result_format((matcher::Result)_actual) << " but it should be " << matcher::result_format((matcher::Result)expected); throw TestFailed(ss.str()); } void ActualMatcherResult::operator!=(int expected) const { if (expected != _actual) return; std::stringstream ss; ss << "actual match result is " << matcher::result_format((matcher::Result)_actual) << " but it should not be"; throw TestFailed(ss.str()); } } } dballe-7.7/dballe/core/match-wreport.cc0000644000175000017500000001404312652630043015014 00000000000000#include #include #include #include #include #include using namespace wreport; using namespace std; namespace dballe { MatchedSubset::MatchedSubset(const Subset& r) : r(r), lat(MISSING_INT), lon(MISSING_INT), var_ana_id(0), var_block(0), var_station(0), var_rep_memo(0) { int ye = MISSING_INT, mo = MISSING_INT, da = MISSING_INT, ho = MISSING_INT, mi = MISSING_INT, se = MISSING_INT; // Scan message taking note of significant values for (Subset::const_iterator i = r.begin(); i != r.end(); ++i) { switch (i->code()) { case WR_VAR(0, 1, 1): var_block = &*i; break; case WR_VAR(0, 1, 2): var_station = &*i; break; case WR_VAR(0, 1, 192): var_ana_id = &*i; break; case WR_VAR(0, 1, 194): var_rep_memo = &*i; break; case WR_VAR(0, 4, 1): ye = i->enq(MISSING_INT); break; case WR_VAR(0, 4, 2): mo = i->enq(MISSING_INT); break; case WR_VAR(0, 4, 3): da = i->enq(MISSING_INT); break; case WR_VAR(0, 4, 4): ho = i->enq(MISSING_INT); break; case WR_VAR(0, 4, 5): mi = i->enq(MISSING_INT); break; case WR_VAR(0, 4, 6): se = i->enq(MISSING_INT); break; case WR_VAR(0, 4, 7): se = i->isset() ? lround(i->enqd()) : MISSING_INT; break; case WR_VAR(0, 5, 1): case WR_VAR(0, 5, 2): if (i->isset()) lat = i->enqd() * 100000; break; case WR_VAR(0, 6, 1): case WR_VAR(0, 6, 2): if (i->isset()) lon = i->enqd() * 100000; break; } } // Fill in missing date bits date = Datetime::lower_bound(ye, mo, da, ho, mi, se); } MatchedSubset::~MatchedSubset() { } matcher::Result MatchedSubset::match_var_id(int val) const { for (Subset::const_iterator i = r.begin(); i != r.end(); ++i) { if (const Var* a = i->enqa(WR_VAR(0, 33, 195))) if (a->enqi() == val) return matcher::MATCH_YES; } return matcher::MATCH_NA; } matcher::Result MatchedSubset::match_station_id(int val) const { if (!var_ana_id) return matcher::MATCH_NA; if (!var_ana_id->isset()) return matcher::MATCH_NA; return var_ana_id->enqi() == val ? matcher::MATCH_YES : matcher::MATCH_NO; } matcher::Result MatchedSubset::match_station_wmo(int block, int station) const { if (!var_block) return matcher::MATCH_NA; if (!var_block->isset()) return matcher::MATCH_NA; if (var_block->enqi() != block) return matcher::MATCH_NO; if (station == -1) return matcher::MATCH_YES; if (!var_station) return matcher::MATCH_NA; if (!var_station->isset()) return matcher::MATCH_NA; if (var_station->enqi() != station) return matcher::MATCH_NO; return matcher::MATCH_YES; } matcher::Result MatchedSubset::match_datetime(const DatetimeRange& range) const { if (date.is_missing()) return matcher::MATCH_NA; return range.contains(date) ? matcher::MATCH_YES : matcher::MATCH_NO; } matcher::Result MatchedSubset::match_coords(const LatRange& latrange, const LonRange& lonrange) const { matcher::Result r1 = matcher::MATCH_NA; if (lat != MISSING_INT) r1 = latrange.contains(lat) ? matcher::MATCH_YES : matcher::MATCH_NO; else if (latrange.is_missing()) r1 = matcher::MATCH_YES; matcher::Result r2 = matcher::MATCH_NA; if (lon != MISSING_INT) r2 = lonrange.contains(lon) ? matcher::MATCH_YES : matcher::MATCH_NO; else if (lonrange.is_missing()) r2 = matcher::MATCH_YES; if (r1 == matcher::MATCH_YES && r2 == matcher::MATCH_YES) return matcher::MATCH_YES; if (r1 == matcher::MATCH_NO || r2 == matcher::MATCH_NO) return matcher::MATCH_NO; return matcher::MATCH_NA; } matcher::Result MatchedSubset::match_rep_memo(const char* memo) const { if (!var_rep_memo) return matcher::MATCH_NA; if (!var_rep_memo->isset()) return matcher::MATCH_NA; return strcmp(memo, var_rep_memo->enqc()) == 0 ? matcher::MATCH_YES : matcher::MATCH_NO; } MatchedBulletin::MatchedBulletin(const wreport::Bulletin& r) : r(r) { subsets = new const MatchedSubset*[r.subsets.size()]; for (unsigned i = 0; i < r.subsets.size(); ++i) subsets[i] = new MatchedSubset(r.subsets[i]); } MatchedBulletin::~MatchedBulletin() { for (unsigned i = 0; i < r.subsets.size(); ++i) delete subsets[i]; delete[] subsets; } matcher::Result MatchedBulletin::match_var_id(int val) const { for (unsigned i = 0; i < r.subsets.size(); ++i) if (subsets[i]->match_var_id(val) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedBulletin::match_station_id(int val) const { for (unsigned i = 0; i < r.subsets.size(); ++i) if (subsets[i]->match_station_id(val) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedBulletin::match_station_wmo(int block, int station) const { for (unsigned i = 0; i < r.subsets.size(); ++i) if (subsets[i]->match_station_wmo(block, station) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedBulletin::match_datetime(const DatetimeRange& range) const { for (unsigned i = 0; i < r.subsets.size(); ++i) if (subsets[i]->match_datetime(range) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedBulletin::match_coords(const LatRange& latrange, const LonRange& lonrange) const { for (unsigned i = 0; i < r.subsets.size(); ++i) if (subsets[i]->match_coords(latrange, lonrange) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedBulletin::match_rep_memo(const char* memo) const { for (unsigned i = 0; i < r.subsets.size(); ++i) if (subsets[i]->match_rep_memo(memo) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } } dballe-7.7/dballe/core/matcher.cc0000644000175000017500000001405212652630043013643 00000000000000#include "matcher.h" #include "defs.h" #include "query.h" #include #include #include using namespace std; using namespace wreport; namespace dballe { matcher::Result Matched::match_var_id(int) const { return matcher::MATCH_NA; } matcher::Result Matched::match_station_id(int) const { return matcher::MATCH_NA; } matcher::Result Matched::match_station_wmo(int, int) const { return matcher::MATCH_NA; } matcher::Result Matched::match_datetime(const DatetimeRange&) const { return matcher::MATCH_NA; } matcher::Result Matched::match_coords(const LatRange&, const LonRange&) const { return matcher::MATCH_NA; } matcher::Result Matched::match_rep_memo(const char* memo) const { return matcher::MATCH_NA; } matcher::Result Matched::int_in_range(int val, int min, int max) { if (min != MISSING_INT && val < min) return matcher::MATCH_NO; if (max != MISSING_INT && max < val) return matcher::MATCH_NO; return matcher::MATCH_YES; } matcher::Result Matched::lon_in_range(int val, int min, int max) { if (min == MISSING_INT && max == MISSING_INT) return matcher::MATCH_YES; if (min == MISSING_INT || max == MISSING_INT) throw error_consistency("both minimum and maximum values must be set when matching longitudes"); if (min < max) return (val >= min && val <= max) ? matcher::MATCH_YES : matcher::MATCH_NO; else return ((val >= min && val <= 18000000) || (val >= -18000000 && val <= max)) ? matcher::MATCH_YES : matcher::MATCH_NO; } namespace matcher { std::string result_format(Result res) { switch (res) { case MATCH_YES: return "yes"; case MATCH_NO: return "no"; case MATCH_NA: return "n/a"; } return "unknown"; } struct And : public Matcher { /** * Matchers added to exprs are *owned* and will be deallocated in the * destructor */ std::vector exprs; virtual ~And() { for (std::vector::iterator i = exprs.begin(); i != exprs.end(); ++i) delete *i; } Result match(const Matched& item) const { if (exprs.empty()) return MATCH_YES; Result res = MATCH_NA; for (std::vector::const_iterator i = exprs.begin(); i != exprs.end() && res != MATCH_NO; ++i) { switch ((*i)->match(item)) { case MATCH_YES: res = MATCH_YES; break; case MATCH_NO: res = MATCH_NO; break; case MATCH_NA: break; } } return res; } virtual void to_record(dballe::Record& rec) const { for (std::vector::const_iterator i = exprs.begin(); i != exprs.end(); ++i) (*i)->to_record(rec); } }; struct AnaIDMatcher : public Matcher { // Station ID to match int ana_id; AnaIDMatcher(int ana_id) : ana_id(ana_id) {} virtual Result match(const Matched& v) const { return v.match_station_id(ana_id) == MATCH_YES ? MATCH_YES : MATCH_NO; } virtual void to_record(Record& rec) const { rec.set("ana_id", ana_id); } }; struct WMOMatcher : public Matcher { int block; int station; WMOMatcher(int block, int station=-1) : block(block), station(station) {} virtual Result match(const Matched& v) const { return v.match_station_wmo(block, station) == MATCH_YES ? MATCH_YES : MATCH_NO; } virtual void to_record(Record& rec) const { rec.set("block", block); if (station != -1) rec.set("station", station); else rec.unset("station"); } }; struct DateMatcher : public Matcher { DatetimeRange range; DateMatcher(const DatetimeRange& range) : range(range) {} virtual Result match(const Matched& v) const { return v.match_datetime(range) == MATCH_YES ? MATCH_YES : MATCH_NO; } virtual void to_record(Record& rec) const { rec.set_datetimerange(range); } }; struct CoordMatcher : public Matcher { LatRange latrange; LonRange lonrange; CoordMatcher(const LatRange& latrange, const LonRange& lonrange) : latrange(latrange), lonrange(lonrange) {} virtual Result match(const Matched& v) const { return v.match_coords(latrange, lonrange) == MATCH_YES ? MATCH_YES : MATCH_NO; } virtual void to_record(Record& rec) const { rec.set_latrange(latrange); rec.set_lonrange(lonrange); } }; static string tolower(const std::string& s) { string res(s); for (string::iterator i = res.begin(); i != res.end(); ++i) *i = ::tolower(*i); return res; } struct ReteMatcher : public Matcher { string rete; ReteMatcher(const std::string& rete) : rete(tolower(rete)) {} virtual Result match(const Matched& v) const { return v.match_rep_memo(rete.c_str()) == MATCH_YES ? MATCH_YES : MATCH_NO; } virtual void to_record(Record& rec) const { rec.set("rep_memo", rete.c_str()); } }; } std::unique_ptr Matcher::create(const dballe::Query& query_gen) { using namespace matcher; const core::Query& query = core::Query::downcast(query_gen); std::unique_ptr res(new And); if (query.ana_id != MISSING_INT) res->exprs.push_back(new AnaIDMatcher(query.ana_id)); if (query.block != MISSING_INT) { if (query.station != MISSING_INT) res->exprs.push_back(new WMOMatcher(query.block, query.station)); else res->exprs.push_back(new WMOMatcher(query.block)); } if (!query.datetime.is_missing()) res->exprs.push_back(new DateMatcher(query.datetime)); if (!query.latrange.is_missing() || !query.lonrange.is_missing()) res->exprs.push_back(new CoordMatcher(query.latrange, query.lonrange)); if (!query.rep_memo.empty()) res->exprs.push_back(new ReteMatcher(query.rep_memo)); return unique_ptr(res.release()); } } dballe-7.7/dballe/core/json.cc0000644000175000017500000002213012652630043013165 00000000000000#include "json.h" #include #include using namespace std; namespace dballe { namespace core { JSONWriter::JSONWriter(std::ostream& out) : out(out) {} JSONWriter::~JSONWriter() {} void JSONWriter::reset() { stack.clear(); } void JSONWriter::val_head() { if (!stack.empty()) { switch (stack.back()) { case LIST_FIRST: stack.back() = LIST; break; case LIST: out << ','; break; case MAPPING_KEY_FIRST: stack.back() = MAPPING_VAL; break; case MAPPING_KEY: out << ','; stack.back() = MAPPING_VAL; break; case MAPPING_VAL: out << ':'; stack.back() = MAPPING_KEY; break; } } } void JSONWriter::add_null() { val_head(); out << "null"; } void JSONWriter::add_bool(bool val) { val_head(); out << (val ? "true" : "false" ); } void JSONWriter::add_int(int val) { val_head(); out << to_string(val); } void JSONWriter::add_double(double val) { val_head(); double vint, vfrac; vfrac = modf(val, &vint); if (vfrac == 0.0) { out << to_string((int)vint); out << ".0"; } else out << to_string(val); } void JSONWriter::add_cstring(const char* val) { val_head(); out << '"'; for ( ; *val; ++val) switch (*val) { case '"': out << "\\\""; break; case '\\': out << "\\\\"; break; case '/': out << "\\/"; break; case '\b': out << "\\b"; break; case '\f': out << "\\f"; break; case '\n': out << "\\n"; break; case '\r': out << "\\r"; break; case '\t': out << "\\t"; break; default: out << *val; break; } out << '"'; } void JSONWriter::add_string(const std::string& val) { add_cstring(val.c_str()); } void JSONWriter::add_level(const Level& val) { start_list(); if (val.ltype1 != MISSING_INT) add(val.ltype1); else add_null(); if (val.l1 != MISSING_INT) add(val.l1); else add_null(); if (val.ltype2 != MISSING_INT) add(val.ltype2); else add_null(); if (val.l2 != MISSING_INT) add(val.l2); else add_null(); end_list(); } void JSONWriter::add_trange(const Trange& val) { start_list(); if (val.pind != MISSING_INT) add(val.pind); else add_null(); if (val.p1 != MISSING_INT) add(val.p1); else add_null(); if (val.p2 != MISSING_INT) add(val.p2); else add_null(); end_list(); } void JSONWriter::add_coords(const Coords& val) { start_list(); if (val.lat != MISSING_INT) add(val.lat); else add_null(); if (val.lon != MISSING_INT) add(val.lon); else add_null(); end_list(); } void JSONWriter::add_datetime(const Datetime& val) { if (val.is_missing()) add_null(); else { start_list(); if (val.year != MISSING_INT) add(val.year); else add_null(); if (val.month != MISSING_INT) add(val.month); else add_null(); if (val.day != MISSING_INT) add(val.day); else add_null(); if (val.hour != MISSING_INT) add(val.hour); else add_null(); if (val.minute != MISSING_INT) add(val.minute); else add_null(); if (val.second != MISSING_INT) add(val.second); else add_null(); end_list(); } } void JSONWriter::add_number(const std::string& val) { val_head(); out << val; } void JSONWriter::add_var(const wreport::Var& val) { if (val.isset()) { if (val.info()->type == wreport::Vartype::String || val.info()->type == wreport::Vartype::Binary) { add_string(val.format()); } else { add_number(val.format()); } } else { add_null(); } } void JSONWriter::add_break() { out << "\n"; } void JSONWriter::start_list() { val_head(); out << '['; stack.push_back(LIST_FIRST); } void JSONWriter::end_list() { out << ']'; stack.pop_back(); } void JSONWriter::start_mapping() { val_head(); out << '{'; stack.push_back(MAPPING_KEY_FIRST); } void JSONWriter::end_mapping() { out << '}'; stack.pop_back(); } struct JSONParseException : public std::runtime_error { using std::runtime_error::runtime_error; }; static void parse_spaces(std::istream& in) { while (isspace(in.peek())) in.get(); } static void parse_fixed(std::istream& in, const char* expected) { const char* s = expected; while (*s) { int c = in.get(); if (c != *s) { if (c == EOF) // throw JSONParseException(str::fmtf("end of file reached looking for %s in %s", s, expected)); throw JSONParseException("unexpected end of file reached"); else // throw JSONParseException(str::fmtf("unexpected character '%c' looking for %s in %s", c, s, expected)); throw JSONParseException("unexpected character"); } ++s; } } static void parse_number(std::istream& in, JSONReader& e) { string num; bool done = false; bool is_double = false; while (!done) { int c = in.peek(); switch (c) { case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': num.append(1, in.get()); break; case '.': case 'e': case 'E': case '+': is_double = true; num.append(1, in.get()); break; default: done = true; } } if (is_double) { e.on_add_double(strtod(num.c_str(), NULL)); } else { e.on_add_int(strtoll(num.c_str(), NULL, 10)); } parse_spaces(in); } static void parse_string(std::istream& in, JSONReader& e) { string res; in.get(); // Eat the leading '"' bool done = false; while (!done) { int c = in.get(); switch (c) { case '\\': c = in.get(); if (c == EOF) throw JSONParseException("unterminated string"); switch (c) { case 'b': res.append(1, '\b'); break; case 'f': res.append(1, '\f'); break; case 'n': res.append(1, '\n'); break; case 'r': res.append(1, '\r'); break; case 't': res.append(1, '\t'); break; default: res.append(1, c); break; } break; case '"': done = true; break; case EOF: throw JSONParseException("unterminated string"); default: res.append(1, c); break; } } parse_spaces(in); e.on_add_string(res); } static void parse_value(std::istream& in, JSONReader& e); static void parse_array(std::istream& in, JSONReader& e) { e.on_start_list(); in.get(); // Eat the leading '[' parse_spaces(in); while (in.peek() != ']') { parse_value(in, e); if (in.peek() == ',') in.get(); parse_spaces(in); } in.get(); // Eat the trailing ']' parse_spaces(in); e.on_end_list(); } static void parse_object(std::istream& in, JSONReader& e) { e.on_start_mapping(); in.get(); // Eat the leading '{' parse_spaces(in); while (in.peek() != '}') { if (in.peek() != '"') throw JSONParseException("expected a string as object key"); parse_string(in, e); parse_spaces(in); if (in.peek() == ':') in.get(); else throw JSONParseException("':' expected after object key"); parse_value(in, e); if (in.peek() == ',') in.get(); parse_spaces(in); } in.get(); // Eat the trailing '}' parse_spaces(in); e.on_end_mapping(); } static void parse_value(std::istream& in, JSONReader& e) { parse_spaces(in); switch (in.peek()) { case EOF: throw JSONParseException("JSON string is truncated"); case '{': parse_object(in, e); break; case '[': parse_array(in, e); break; case '"': parse_string(in, e); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': parse_number(in, e); break; case 't': parse_fixed(in, "true"); e.on_add_bool(true); parse_spaces(in); break; case 'f': parse_fixed(in, "false"); e.on_add_bool(false); parse_spaces(in); break; case 'n': parse_fixed(in, "null"); e.on_add_null(); parse_spaces(in); break; default: // throw JSONParseException(str::fmtf("unexpected character '%c'", in.peek())); throw JSONParseException("unexpected character"); } parse_spaces(in); } void JSONReader::parse(std::istream& in) { parse_value(in, *this); } } } dballe-7.7/dballe/core/vasprintf.h0000644000175000017500000000375312652630043014104 00000000000000#ifndef DBALLE_CORE_VASPRINTF_H #define DBALLE_CORE_VASPRINTF_H #include "config.h" #include #include #include #include #if USE_OWN_VASPRINTF static int vasprintf (char **result, const char *format, va_list args) { const char *p = format; /* Add one to make sure that it is never zero, which might cause malloc to return NULL. */ int total_width = strlen (format) + 1; va_list ap; memcpy ((void *)&ap, (void *)&args, sizeof (va_list)); while (*p != '\0') { if (*p++ == '%') { while (strchr ("-+ #0", *p)) ++p; if (*p == '*') { ++p; total_width += abs (va_arg (ap, int)); } else total_width += strtoul (p, (char **) &p, 10); if (*p == '.') { ++p; if (*p == '*') { ++p; total_width += abs (va_arg (ap, int)); } else total_width += strtoul (p, (char **) &p, 10); } while (strchr ("hlL", *p)) ++p; /* Should be big enough for any format specifier except %s and floats. */ total_width += 30; switch (*p) { case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': case 'c': (void) va_arg (ap, int); break; case 'f': case 'e': case 'E': case 'g': case 'G': (void) va_arg (ap, double); /* Since an ieee double can have an exponent of 307, we'll make the buffer wide enough to cover the gross case. */ total_width += 307; break; case 's': total_width += strlen (va_arg (ap, char *)); break; case 'p': case 'n': (void) va_arg (ap, char *); break; } p++; } } *result = (char*)malloc (total_width); if (*result != NULL) { return vsprintf (*result, format, args);} else { return 0; } } static int asprintf (char **result, const char *format, ...) { va_list ap; va_start(ap, format); int res = vasprintf(result, format, ap); va_end(ap); return res; } #endif #endif dballe-7.7/dballe/core/csv-test.cc0000644000175000017500000001666012652630043013777 00000000000000#include "tests.h" #include "csv.h" #include #include using namespace std; using namespace dballe; using namespace dballe::tests; namespace { class TestCSVWriter : public CSVWriter { public: stringstream buf; virtual void flush_row() { buf << row; } }; class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { // Test CSV string escaping add_method("escape", []() { stringstream s; csv_output_quoted_string(s, ""); wassert(actual(s.str()) == ""); wassert(actual(CSVReader::unescape(s.str())) == ""); s.str(std::string()); csv_output_quoted_string(s, "1"); wassert(actual(s.str()) == "1"); wassert(actual(CSVReader::unescape(s.str())) == "1"); s.str(std::string()); csv_output_quoted_string(s, "12"); wassert(actual(s.str()) == "12"); wassert(actual(CSVReader::unescape(s.str())) == "12"); s.str(std::string()); csv_output_quoted_string(s, "123"); wassert(actual(s.str()) == "123"); wassert(actual(CSVReader::unescape(s.str())) == "123"); s.str(std::string()); csv_output_quoted_string(s, ","); wassert(actual(s.str()) == "\",\""); wassert(actual(CSVReader::unescape(s.str())) == ","); s.str(std::string()); csv_output_quoted_string(s, "antani, blinda"); wassert(actual(s.str()) == "\"antani, blinda\""); wassert(actual(CSVReader::unescape(s.str())) == "antani, blinda"); s.str(std::string()); csv_output_quoted_string(s, "antani, \"blinda\""); wassert(actual(s.str()) == "\"antani, \"\"blinda\"\"\""); wassert(actual(CSVReader::unescape(s.str())) == "antani, \"blinda\""); s.str(std::string()); csv_output_quoted_string(s, "\""); wassert(actual(s.str()) == "\"\"\"\""); wassert(actual(CSVReader::unescape(s.str())) == "\""); s.str(std::string()); csv_output_quoted_string(s, "\",\""); wassert(actual(s.str()) == "\"\"\",\"\"\""); wassert(actual(CSVReader::unescape(s.str())) == "\",\""); wassert(actual(CSVReader::unescape("\"")) == "\""); wassert(actual(CSVReader::unescape("\"\"")) == ""); wassert(actual(CSVReader::unescape("\"\"\"")) == "\""); wassert(actual(CSVReader::unescape("\"\"\"\"")) == "\""); wassert(actual(CSVReader::unescape("\"\"\"\"\"")) == "\"\""); wassert(actual(CSVReader::unescape("a\"b")) == "a\"b"); }); // Test CSV reader add_method("reader", []() { { stringstream in(""); CSVReader reader(in); wassert(actual(reader.next()).isfalse()); } { stringstream in("\n"); CSVReader reader(in); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 1); wassert(actual(reader.cols[0]) == ""); wassert(actual(reader.next()).isfalse()); } { stringstream in("\r\n"); CSVReader reader(in); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 1); wassert(actual(reader.cols[0]) == ""); wassert(actual(reader.next()).isfalse()); } { stringstream in("1,2\r\n"); CSVReader reader(in); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 2u); wassert(actual(reader.cols[0]) == "1"); wassert(actual(reader.cols[1]) == "2"); wassert(actual(reader.next()).isfalse()); } { stringstream in("1\r\n2\r\n"); CSVReader reader(in); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 1u); wassert(actual(reader.cols[0]) == "1"); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 1u); wassert(actual(reader.cols[0]) == "2"); wassert(actual(reader.next()).isfalse()); } { stringstream in("1,2\n"); CSVReader reader(in); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 2u); wassert(actual(reader.cols[0]) == "1"); wassert(actual(reader.cols[1]) == "2"); wassert(actual(reader.next()).isfalse()); } { stringstream in( "1,\",\",2\n" "antani,,blinda\n" ",\n" ); CSVReader reader(in); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 3u); wassert(actual(reader.cols[0]) == "1"); wassert(actual(reader.cols[1]) == ","); wassert(actual(reader.cols[2]) == "2"); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 3u); wassert(actual(reader.cols[0]) == "antani"); wassert(actual(reader.cols[1]) == ""); wassert(actual(reader.cols[2]) == "blinda"); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 2u); wassert(actual(reader.cols[0]) == ""); wassert(actual(reader.cols[1]) == ""); wassert(actual(reader.next()).isfalse()); } { stringstream in("1,2"); CSVReader reader(in); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 2u); wassert(actual(reader.cols[0]) == "1"); wassert(actual(reader.cols[1]) == "2"); wassert(actual(reader.next()).isfalse()); } { stringstream in("\"1\"\r\n"); CSVReader reader(in); wassert(actual(reader.next()).istrue()); wassert(actual(reader.cols.size()) == 1u); wassert(actual(reader.cols[0]) == "1"); wassert(actual(reader.next()).isfalse()); } }); // Test write/read cycles add_method("writer", []() { TestCSVWriter out; out.add_value(1); out.add_value("\""); out.add_value("'"); out.add_value(","); out.add_value("\n"); out.flush_row(); out.buf.seekg(0); CSVReader in(out.buf); wassert(actual(in.next()).istrue()); wassert(actual(in.cols.size()) == 5); wassert(actual(in.as_int(0)) == 1); wassert(actual(in.cols[1]) == "\""); wassert(actual(in.cols[2]) == "'"); wassert(actual(in.cols[3]) == ","); wassert(actual(in.cols[4]) == "\n"); wassert(actual(in.next()).isfalse()); }); } } test("core_csv"); } dballe-7.7/dballe/core/aoffile.cc0000644000175000017500000002331512652630043013627 00000000000000/* * dballe/aoffile - AOF File I/O * * Copyright (C) 2005--2010 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "aoffile.h" #include #include #include #include "dballe/core/byteswap.h" #include using namespace wreport; using namespace std; namespace dballe { namespace core { AofFile::AofFile(const std::string& name, FILE* fd, bool close_on_exit) : File(name, fd, close_on_exit) {} AofFile::~AofFile() {} BinaryMessage AofFile::read() { BinaryMessage res(AOF); res.pathname = m_name; res.offset = ftello(fd); // If we are at the beginning of the file, skip the file header if (res.offset == 0) { read_header(); res.offset = ftello(fd); } // Read the Observation Header read_record(res.data); if (res.data.empty()) return BinaryMessage(AOF); const uint32_t* rec = (const uint32_t*)res.data.data(); if (rec[1] != 4) error_parse::throwf(m_name.c_str(), ftell(fd), "value '01 length of preliminary record' should be 4, either big or little endian (it is %d (%08x) instead)", rec[1], rec[1]); res.index = idx++; return res; } void AofFile::write(const std::string& msg) { off_t pos = ftello(fd); if (pos == -1 && errno != ESPIPE) error_system::throwf("cannot read the current position in output file %s", m_name.c_str()); /* If it's a non-seekable file, we use idx to see if we're at the beginning */ if (pos == -1 && errno == ESPIPE && idx == 0) pos = 0; /* If we are at the beginning of the file, write a dummy header */ if (pos == 0) write_dummy_header(); write_record(msg); } bool AofFile::read_record(std::string& res) { uint32_t len_word, len_word1; int swapwords = 0; /* Read the first Fortran length of record word */ if (fread(&len_word, 4, 1, fd) == 0) { if (feof(fd)) { return false; } error_system::throwf("reading a record-length first word in %s", m_name.c_str()); } if ((len_word & 0xFF000000) != 0) { swapwords = 1; len_word = bswap_32(len_word); } if (len_word % 4 != 0) error_parse::throwf(m_name.c_str(), ftell(fd), "length of record (%d) is not a multiple of 4", len_word); // Allocate space res.resize(len_word); // Read the record uint32_t* buf = (uint32_t*)res.data(); if (fread(buf, len_word, 1, fd) == 0) { error_system::throwf("reading a %d-bytes record from %s", len_word, m_name.c_str()); } // Read the last Fortran length of record word if (fread(&len_word1, 4, 1, fd) == 0) error_system::throwf("reading a record-length last word in %s", m_name.c_str()); // Swap words if needed if (swapwords) { for (unsigned i = 0; i < len_word / 4; i++) buf[i] = bswap_32(buf[i]); len_word1 = bswap_32(len_word1); } if (len_word != len_word1) throw error_parse(m_name.c_str(), ftell(fd), "initial length of record is different than the final length of record"); return true; } static enum { INVALID = 0, END_ARCH = 1, END_LE = 2, END_BE = 3 } writer_endianness = INVALID; static void init_writer_endiannes_if_needed() { if (writer_endianness == INVALID) { char* env_swap = getenv("DBA_AOF_ENDIANNESS"); if (env_swap == NULL) writer_endianness = END_ARCH; else if (strcmp(env_swap, "ARCH") == 0) writer_endianness = END_ARCH; else if (strcmp(env_swap, "LE") == 0) writer_endianness = END_LE; else if (strcmp(env_swap, "BE") == 0) writer_endianness = END_BE; else writer_endianness = END_ARCH; } } void AofFile::write_word(uint32_t word) { uint32_t oword; switch (writer_endianness) { case END_ARCH: oword = word; break; #if __BYTE_ORDER == __BIG_ENDIAN case END_LE: oword = bswap_32(word); break; case END_BE: oword = word; break; #else #if __BYTE_ORDER == __LITTLE_ENDIAN case END_LE: oword = word; break; case END_BE: oword = bswap_32(word); break; #else case END_LE: oword = bswap_32(htonl(word)); break; case END_BE: oword = htonl(word); break; #endif #endif case INVALID: throw error_consistency("trying to write a word without knowing its endianness"); } if (fwrite(&oword, sizeof(uint32_t), 1, fd) != 1) error_system::throwf("writing 4 bytes on %s", m_name.c_str()); } void AofFile::write_record(const std::string& res) { const uint32_t* rec = (const uint32_t*)res.data(); write_record(rec, res.size() / sizeof(uint32_t)); } void AofFile::write_record(const uint32_t* words, size_t wordcount) { init_writer_endiannes_if_needed(); /* Write the leading length of record word */ write_word(wordcount * sizeof(uint32_t)); for (unsigned i = 0; i < wordcount; ++i) write_word(words[i]); /* Write the trailing length of record word */ write_word(wordcount * sizeof(uint32_t)); } // Read the file header, performing some consistency checks then discarding // the data void AofFile::read_header() { string buf; /* Read the First Data Record */ if (!read_record(buf)) throw error_parse(m_name.c_str(), ftell(fd), "AOF file is empty or does not contain AOF data"); if (buf.size() / sizeof(uint32_t) != 14) error_parse::throwf(m_name.c_str(), ftell(fd), "FDR contains %zd octets instead of 14", buf.size()); uint32_t* fdr = (uint32_t*)buf.data(); /* Consistency checks */ if (fdr[0] != 14) error_parse::throwf(m_name.c_str(), ftell(fd), "first word of FDR is %d instead of 14", fdr[0]); /* Read Data Descriptor Record */ if (!read_record(buf)) error_parse::throwf(m_name.c_str(), ftell(fd), "AOF file is truncated after First Data Record"); if (buf.size() / sizeof(uint32_t) != 17) error_parse::throwf(m_name.c_str(), ftell(fd), "DDR contains %zd octets instead of 17", buf.size()); // uint32_t* ddr = (uint32_t*)buf.data(); #if 0 reader->start.tm_hour = ddr[10] % 100; reader->start.tm_mday = ((ddr[10] / 100) % 100); reader->start.tm_mon = ((ddr[10] / 10000) % 100) - 1; reader->start.tm_year = (ddr[10] / 1000000) - 1900; reader->end.tm_hour = ddr[12] % 100; reader->end.tm_mday = ((ddr[12] / 100) % 100); reader->end.tm_mon = ((ddr[12] / 10000) % 100) - 1; reader->end.tm_year = (ddr[12] / 1000000) - 1900; #endif } void AofFile::write_dummy_header() { uint32_t fdr[14]; uint32_t ddr[17]; /* Use 'now' for start and end times */ time_t tnow = time(NULL); struct tm* now = gmtime(&tnow); struct tm* start = now; struct tm* end = now; /* Write FDR */ fdr[ 0] = 14; fdr[ 1] = 13; fdr[ 2] = 0; fdr[ 3] = 2048; fdr[ 4] = 2; fdr[ 5] = (now->tm_year + 1900) * 10000 + (now->tm_mon + 1) * 100 + now->tm_mday; fdr[ 6] = now->tm_hour * 100 + now->tm_min; fdr[ 7] = ((uint32_t)1 << 31) - 1; fdr[ 8] = 1; fdr[ 9] = 60; fdr[10] = ((uint32_t)1 << 31) - 1; fdr[11] = ((uint32_t)1 << 31) - 1; fdr[12] = 1; fdr[13] = ((uint32_t)1 << 31) - 1; write_record(fdr, 14); /* Write DDR */ ddr[ 0] = 17; ddr[ 1] = 16; ddr[ 2] = 0; ddr[ 3] = 820; ddr[ 4] = 2; ddr[ 5] = (now->tm_year + 1900) * 10000 + (now->tm_mon + 1) * 100 + now->tm_mday; ddr[ 6] = now->tm_hour * 100 + now->tm_min; ddr[ 7] = ((uint32_t)1 << 31) - 1; ddr[ 8] = ((uint32_t)1 << 31) - 1; ddr[ 9] = 60; ddr[10] = (start->tm_year + 1900) * 1000000 + (start->tm_mon + 1) * 10000 + (start->tm_mday * 100) + start->tm_hour; ddr[11] = 1; ddr[12] = (end->tm_year + 1900) * 1000000 + (end->tm_mon + 1) * 10000 + (end->tm_mday * 100) + end->tm_hour; ddr[13] = ((uint32_t)1 << 31) - 1; ddr[14] = ((uint32_t)1 << 31) - 1; ddr[15] = 2; ddr[16] = ((uint32_t)1 << 31) - 1; write_record(ddr, 17); } void AofFile::fix_header() { string buf; uint32_t start = 0xffffffff; uint32_t end = 0; size_t pos = 0; /* Read the FDR */ read_record(buf); pos += buf.size(); /* Read the DDR */ read_record(buf); pos += buf.size(); /* Iterate through all the records in the file */ while (read_record(buf)) { if (buf.size() < 11) error_parse::throwf(m_name.c_str(), pos, "observation record is too short (%zd bytes)", buf.size()); const uint32_t* rec = (const uint32_t*)buf.data(); /* Compute the extremes of start and end */ uint32_t cur = rec[10-1] * 100 + rec[11-1]/100; if (cur < start) start = cur; if (cur > end) end = cur; pos += buf.size(); } /* Update the header with the new extremes */ /* Check if we need to swap bytes to match the header encoding */ if (fseek(fd, 0, SEEK_SET) == -1) error_system::throwf("trying to seek to start of file %s", m_name.c_str()); uint32_t endianness_test; if (fread(&endianness_test, 4, 1, fd) == 0) error_system::throwf("reading the first word of file %s", m_name.c_str()); if ((endianness_test & 0xFF000000) != 0) { start = bswap_32(start); end = bswap_32(end); } /* Write start of observation period */ if (fseek(fd, 14 + 10, SEEK_SET) == -1) error_system::throwf("trying to seek in file %s", m_name.c_str()); if (fwrite(&start, sizeof(uint32_t), 1, fd) != 1) error_system::throwf("rewriting 4 bytes on %s", m_name.c_str()); /* Write end of observation period */ if (fseek(fd, 14 + 12, SEEK_SET) == -1) error_system::throwf("trying to seek in file %s", m_name.c_str()); if (fwrite(&end, sizeof(uint32_t), 1, fd) != 1) error_system::throwf("rewriting 4 bytes on %s", m_name.c_str()); } } } dballe-7.7/dballe/core/var.cc0000644000175000017500000000672012652630043013013 00000000000000/* * dballe/var - DB-All.e specialisation of wreport variable * * Copyright (C) 2005,2010 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "var.h" #include using namespace wreport; using namespace std; namespace dballe { void format_code(wreport::Varcode code, char* buf) { // Format variable code char type; switch (WR_VAR_F(code)) { case 0: type = 'B'; break; case 1: type = 'R'; break; case 2: type = 'C'; break; case 3: type = 'D'; break; default: type = '?'; break; } snprintf(buf, 7, "%c%02d%03d", type, WR_VAR_X(code), WR_VAR_Y(code)); } void resolve_varlist(const std::string& varlist, std::function dest) { if (varlist.empty()) throw error_consistency("cannot parse a Varcode list out of an empty string"); size_t beg = 0; while (true) { size_t end = varlist.find(',', beg); if (end == string::npos) { dest(resolve_varcode(varlist.substr(beg))); break; } else { dest(resolve_varcode(varlist.substr(beg, end-beg))); } beg = end + 1; } } void resolve_varlist(const std::string& varlist, std::set& out) { resolve_varlist(varlist, [&](wreport::Varcode code) { out.insert(code); }); } wreport::Varcode map_code_to_dballe(wreport::Varcode code) { switch (code) { case WR_VAR(0, 7, 1): return WR_VAR(0, 7, 30); case WR_VAR(0, 10, 3): return WR_VAR(0, 10, 8); case WR_VAR(0, 10, 61): return WR_VAR(0, 10, 60); case WR_VAR(0, 12, 1): return WR_VAR(0, 12, 101); case WR_VAR(0, 12, 2): return WR_VAR(0, 12, 102); case WR_VAR(0, 12, 3): return WR_VAR(0, 12, 103); default: return code; } } std::unique_ptr var_copy_without_unset_attrs(const wreport::Var& var) { unique_ptr copy(newvar(var.code())); copy->setval(var); // Copy value performing conversions for (const Var* a = var.next_attr(); a; a = a->next_attr()) { // Skip undefined attributes if (!a->isset()) continue; auto acopy = newvar(map_code_to_dballe(a->code())); acopy->setval(*a); copy->seta(move(acopy)); } return copy; } std::unique_ptr var_copy_without_unset_attrs( const wreport::Var& var, wreport::Varcode code) { unique_ptr copy(newvar(code)); copy->setval(var); // Copy value performing conversions for (const Var* a = var.next_attr(); a; a = a->next_attr()) { // Skip undefined attributes if (!a->isset()) continue; auto acopy = newvar(map_code_to_dballe(a->code())); acopy->setval(*a); copy->seta(move(acopy)); } return copy; } } dballe-7.7/dballe/core/verbose.h0000644000175000017500000000375212652630043013534 00000000000000/* * DB-ALLe - Archive for punctual meteorological data * * Copyright (C) 2005,2006 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBA_VERBOSE_H #define DBA_VERBOSE_H #ifdef __cplusplus extern "C" { #endif /** @file * @ingroup core * Debugging aid framework that allows to print, at user request, runtime * verbose messages about internal status and operation. */ /** * The output stream where verbose messages will be sent */ #define DBA_VERBOSE_STREAM stderr /** * The various contexts for verbose messages (they will be OR-ed together) */ enum { DBA_VERB_NONE = 0, DBA_VERB_DB_INPUT = 1, DBA_VERB_DB_SQL = 2, DBA_VERB_BUFREX_MSG = 4, }; /** * Initialize the verbose printing interface, taking the allowed verbose level * from the environment and printing a little informational banner if any * level of verbose messages are enabled. */ void dba_verbose_init(); /// Set the bitmask specifying which messages are printed void dba_verbose_set_mask(int mask); /** * Return 1 if the given verbose level has been requested in output, else 0 */ int dba_verbose_is_allowed(int lev); /** * Output a message on the verbose stream, if the given level of verbosity has * been requested */ void dba_verbose(int lev, const char* fmt, ...); #ifdef __cplusplus } #endif #endif dballe-7.7/dballe/core/matcher-test.cc0000644000175000017500000002206112652630043014617 00000000000000#include "tests.h" #include "matcher.h" #include "record.h" #include #include using namespace std; using namespace dballe; using namespace dballe::core; using namespace dballe::tests; namespace { std::unique_ptr get_matcher(const char* q) { return Matcher::create(*dballe::tests::query_from_string(q)); } class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { // Test station_id matcher add_method("station_id", []() { auto m = get_matcher("ana_id=1"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("ana_id", 2); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("ana_id", 1); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); }); // Test station WMO matcher add_method("station_wmo", []() { { auto m = get_matcher("block=11"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("block", 1); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("block", 11); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); matched.set("station", 222); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); } { auto m = get_matcher("block=11, station=222"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("block", 1); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("block", 11); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("station", 22); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("station", 222); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); matched.set("block", 1); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.unset("block"); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); } }); // Test date matcher add_method("date", []() { { auto m = get_matcher("yearmin=2000"); core::Record matched; wassert(actual(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("year", 1999); wassert(actual(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("year", 2000); wassert(actual(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); } { auto m = get_matcher("yearmax=2000"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("year", 2001); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("year", 2000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); } { auto m = get_matcher("yearmin=2000, yearmax=2010"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("year", 1999); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("year", 2011); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("year", 2000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); matched.set("year", 2005); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); matched.set("year", 2010); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); } }); // Test coordinates matcher add_method("coords", []() { { auto m = get_matcher("latmin=45.00"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lat", 43.0); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lat", 45.0); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); matched.set("lat", 46.0); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); } { auto m = get_matcher("latmax=45.00"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lat", 4600000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lat", 4500000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); matched.set("lat", 4400000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); } { auto m = get_matcher("lonmin=45.00, lonmax=180.0"); core::Record matched; wassert(actual(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lon", 4300000); wassert(actual(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lon", 4500000); wassert(actual(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); matched.set("lon", 4500000); wassert(actual(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); } { auto m = get_matcher("lonmin=-180, lonmax=45.0"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lon", 4600000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lon", 4500000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); matched.set("lon", 4400000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); } { auto m = get_matcher("latmin=45.0, latmax=46.0, lonmin=10.0, lonmax=12.0"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lat", 4550000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lon", 1300000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("lon", 1100000); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); } }); // Test rep_memo matcher add_method("rep_memo", []() { auto m = get_matcher("rep_memo=synop"); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("rep_memo", "temp"); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_NO); matched.set("rep_memo", "synop"); wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); }); // Test empty matcher add_method("empty", []() { auto query = dballe::Query::create(); std::unique_ptr m = Matcher::create(*query); core::Record matched; wassert(actual_matcher_result(m->match(MatchedRecord(matched))) == matcher::MATCH_YES); }); } } test("core_matcher"); } dballe-7.7/dballe/core/values.h0000644000175000017500000001271312652630043013363 00000000000000#ifndef DBALLE_CORE_VALUES_H #define DBALLE_CORE_VALUES_H #include #include #include #include #include namespace dballe { struct Station { std::string report; int ana_id = MISSING_INT; Coords coords; Ident ident; Station() = default; Station(const dballe::Record& rec) { set_from_record(rec); } void clear_ids() { ana_id = MISSING_INT; } void set_from_record(const Record& rec); bool operator==(const Station& o) const { return report == o.report && ana_id == o.ana_id && coords == o.coords && ident == o.ident; } void print(FILE* out, const char* end="\n") const; }; struct Sampling : public Station { Datetime datetime; Level level; Trange trange; Sampling() = default; Sampling(const dballe::Record& rec) { set_from_record(rec); } void set_from_record(const Record& rec); Sampling& operator=(const Sampling&) = default; Sampling& operator=(const Station& st) { Station::operator=(st); return *this; } bool operator==(const Sampling& o) const { return Station::operator==(o) && datetime == o.datetime && level == o.level && trange == o.trange; } void print(FILE* out, const char* end="\n") const; }; namespace values { struct Value { int data_id = MISSING_INT; wreport::Var* var = nullptr; Value(const Value& o) : data_id(o.data_id), var(o.var ? new wreport::Var(*o.var) : nullptr) {} Value(Value&& o) : data_id(o.data_id), var(o.var) { o.var = nullptr; } Value(const wreport::Var& var) : var(new wreport::Var(var)) {} Value(std::unique_ptr&& var) : var(var.release()) {} ~Value() { delete var; } Value& operator=(const Value& o) { if (this == &o) return *this; data_id = o.data_id; delete var; var = o.var ? new wreport::Var(*o.var) : nullptr; return *this; } Value& operator=(Value&& o) { if (this == &o) return *this; data_id = o.data_id; delete var; var = o.var; o.var = nullptr; return *this; } bool operator==(const Value& o) const { if (data_id != o.data_id) return false; if (var == o.var) return true; if (!var || !o.var) return false; return *var == *o.var; } void clear_ids() { data_id = MISSING_INT; } void set(const wreport::Var& v) { delete var; var = new wreport::Var(v); } void set(std::unique_ptr&& v) { delete var; var = v.release(); } void print(FILE* out) const; }; } // FIXME: map, or hashmap, or vector enforced to be unique struct Values : protected std::map { Values() = default; Values(const dballe::Record& rec) { set_from_record(rec); } typedef std::map::const_iterator const_iterator; typedef std::map::iterator iterator; const_iterator begin() const { return std::map::begin(); } const_iterator end() const { return std::map::end(); } iterator begin() { return std::map::begin(); } iterator end() { return std::map::end(); } size_t size() const { return std::map::size(); } bool empty() const { return std::map::empty(); } void clear() { return std::map::clear(); } bool operator==(const Values& o) const; const values::Value& operator[](wreport::Varcode code) const; const values::Value& operator[](const char* code) const { return operator[](resolve_varcode(code)); } const values::Value& operator[](const std::string& code) const { return operator[](resolve_varcode(code)); } const values::Value* get(wreport::Varcode code) const; const values::Value* get(const char* code) const { return get(resolve_varcode(code)); } const values::Value* get(const std::string& code) const { return get(resolve_varcode(code)); } void set(const wreport::Var&); void set(std::unique_ptr&&); template void set(C code, const T& val) { this->set(newvar(code, val)); } void add_data_id(wreport::Varcode code, int data_id); void set_from_record(const Record& rec); void clear_ids() { for (auto& i : *this) i.second.clear_ids(); } void print(FILE* out) const; }; struct StationValues { Station info; Values values; StationValues() = default; StationValues(const dballe::Record& rec) : info(rec), values(rec) {} void set_from_record(const Record& rec); bool operator==(const StationValues& o) const { return info == o.info && values == o.values; } void clear_ids() { info.clear_ids(); values.clear_ids(); } void print(FILE* out) const; }; struct DataValues { Sampling info; Values values; DataValues() = default; DataValues(const dballe::Record& rec) : info(rec), values(rec) {} void set_from_record(const Record& rec); bool operator==(const DataValues& o) const { return info == o.info && values == o.values; } void clear_ids() { info.clear_ids(); values.clear_ids(); } void print(FILE* out) const; }; } #endif dballe-7.7/dballe/core/aoffile.h0000644000175000017500000000534012652630043013467 00000000000000/* * dballe/aoffile - AOF File I/O * * Copyright (C) 2005--2010 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBA_CORE_AOFFILE_H #define DBA_CORE_AOFFILE_H /** @file * @ingroup core * AOF File I/O * * This module provides a dballe::File implementation for AOF files. */ #include #include namespace dballe { namespace core { class AofFile : public dballe::core::File { protected: /** * Read a Fortran Unformatted Sequential Binary record from a file * * @param res * The data read. The resulting data is an array of 32bit words that will * be byteswapped to native endianness if needed. * @return true if a record was found, false on EOF */ bool read_record(std::string& res); /** * Write a Fortran Unformatted Sequential Binary record to a file * * @param res * The data to be written, considered an array of 32bit words that will be * byteswapped for endianness if needed */ void write_record(const std::string& res); /** * Write a Fortran Unformatted Sequential Binary record to a file * * @param words * The data to be written, as an array of 32bit words that will be * byteswapped for endianness if needed */ void write_record(const uint32_t* words, size_t wordcount); /** * Write a word to the file, byteswapping it for endianness if needed */ void write_word(uint32_t word); public: AofFile(const std::string& name, FILE* fd, bool close_on_exit=true); virtual ~AofFile(); virtual Encoding encoding() const override { return AOF; } BinaryMessage read() override; void write(const std::string& msg) override; /** * Read the file header, perform some consistency checks then discard the * data */ void read_header(); /// Write a dummy file header void write_dummy_header(); /** * Rewrite the file header, scanning the file to compute a correct one */ void fix_header(); }; } } #endif dballe-7.7/dballe/core/aliases.h0000644000175000017500000000420512652630043013502 00000000000000/* * wreport/aliases - Aliases for commonly used variable codes * * Copyright (C) 2005--2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef WREPORT_CORE_ALIASES_H #define WREPORT_CORE_ALIASES_H /** @file * @ingroup core * Resolve aliases to variable codes */ #include #include namespace dballe { /** * Resolve a variable alias. * * @param alias * The alias to resolve * @return * The varcode corresponding to the alias, or 0 if no variable has the given * alias. See @ref vartable.h */ wreport::Varcode varcode_alias_resolve(const char* alias); /** * Resolve a variable alias. * * @param alias * The alias to resolve (does not need to be null-terminated) * @param len * The length of the string * @return * The varcode corresponding to the aliase, or 0 if no variable has the given * alias. See @ref vartable.h */ wreport::Varcode varcode_alias_resolve_substring(const char* alias, int len); /** * Resolve a variable alias. * * @param alias * The alias to resolve * @return * The varcode corresponding to the alias, or 0 if no variable has the given * alias. See @ref vartable.h */ wreport::Varcode varcode_alias_resolve(const std::string& alias); /** * Look for the aliase for a Varcode. * * @returns The alias string, or NULL if the varcode has no alias */ const char* varcode_alias_resolve_reverse(wreport::Varcode code); } /* vim:set ts=4 sw=4: */ #endif dballe-7.7/dballe/core/aliases.cc0000644000175000017500000001342112652630120013634 00000000000000/* C++ code produced by gperf version 3.0.4 */ /* Command-line: gperf */ /* Computed positions: -k'$' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif #include #include using namespace wreport; namespace dballe { struct aliasdef { const char* alias; Varcode var; }; #define TOTAL_KEYWORDS 27 #define MIN_WORD_LENGTH 1 #define MAX_WORD_LENGTH 10 #define MIN_HASH_VALUE 1 #define MAX_HASH_VALUE 34 /* maximum key range = 34, duplicates = 0 */ class VarcodeAliases { private: static inline unsigned int hash (const char *str, unsigned int len); public: static struct aliasdef *find (const char *str, unsigned int len); }; inline unsigned int VarcodeAliases::hash (register const char *str, register unsigned int len) { static unsigned char asso_values[] = { 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 30, 35, 10, 30, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 5, 25, 20, 35, 25, 35, 35, 0, 35, 35, 15, 15, 0, 30, 35, 35, 5, 25, 20, 35, 10, 35, 15, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35 }; return len + asso_values[(unsigned char)str[len - 1]]; } static struct aliasdef wordlist[] = { {""}, {"p", WR_VAR(0, 10, 4)}, {"tp", WR_VAR(0, 13, 11)}, {"mwp", WR_VAR(0, 22, 74)}, {"mslp", WR_VAR(0, 10, 51)}, {"block", WR_VAR(0, 1, 1)}, {"t", WR_VAR(0, 12, 101)}, {"td", WR_VAR(0, 12, 103)}, {"mwd", WR_VAR(0, 22, 1)}, {"pp1d", WR_VAR(0, 22, 71)}, {""}, {"height", WR_VAR(0, 7, 30)}, {"data_id", WR_VAR(0, 33, 195)}, {"no2", WR_VAR(0, 15, 193)}, {"tmax", WR_VAR(0, 12, 11)}, {""}, {"z", WR_VAR(0, 10, 3)}, {"no", WR_VAR(0, 15, 192)}, {""}, {"tmin", WR_VAR(0, 12, 12)}, {""}, {"v", WR_VAR(0, 11, 4)}, {"station", WR_VAR(0, 1, 2)}, {""}, {"conf", WR_VAR(0, 33, 7)}, {"heightbaro", WR_VAR(0, 7, 31)}, {"u", WR_VAR(0, 11, 3)}, {"rh", WR_VAR(0, 13, 3)}, {"swh", WR_VAR(0, 22, 70)}, {"name", WR_VAR(0, 1, 19)}, {""}, {"q", WR_VAR(0, 13, 1)}, {"o3", WR_VAR(0, 15, 194)}, {""}, {"pm10", WR_VAR(0, 15, 195)} }; struct aliasdef * VarcodeAliases::find (register const char *str, register unsigned int len) { if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len); if (key <= MAX_HASH_VALUE && key >= 0) { register const char *s = wordlist[key].alias; if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') return &wordlist[key]; } } return 0; } Varcode varcode_alias_resolve(const char* alias) { struct aliasdef* res = VarcodeAliases::find(alias, strlen(alias)); if (res == NULL) return 0; else return res->var; } Varcode varcode_alias_resolve_substring(const char* alias, int len) { struct aliasdef* res = VarcodeAliases::find(alias, len); if (res == NULL) return 0; else return res->var; } wreport::Varcode varcode_alias_resolve(const std::string& alias) { struct aliasdef* res = VarcodeAliases::find(alias.data(), alias.size()); if (res == NULL) return 0; else return res->var; } } /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/core/match-wreport-test.cc0000644000175000017500000005027112652630043015774 00000000000000#include "tests.h" #include "match-wreport.h" #include "var.h" #include #include #include #include #include #include #include using namespace std; using namespace dballe; using namespace dballe::tests; using namespace wreport; namespace { std::unique_ptr get_matcher(const char* q) { return Matcher::create(*dballe::tests::query_from_string(q)); } struct Fixture : public dballe::tests::Fixture { Tables tables; Fixture() { tables.load_bufr(BufrTableID(0, 0, 0, 24, 0)); } }; class TestSubset : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { // Test station_id matcher add_method("station_id", [](Fixture& f) { auto m = get_matcher("ana_id=1"); Tables tables; tables.load_bufr(BufrTableID(200, 0, 0, 14, 1)); Subset s(tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_i(WR_VAR(0, 1, 1), 1); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_i(WR_VAR(0, 1, 192), 1); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); }); // Test station WMO matcher add_method("station_wmo", [](Fixture& f) { { auto m = get_matcher("block=11"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_i(WR_VAR(0, 1, 1), 1); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.back().seti(11); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); s.store_variable_i(WR_VAR(0, 1, 2), 222); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); } { auto m = get_matcher("block=11, station=222"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_i(WR_VAR(0, 1, 1), 1); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.back().seti(11); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_i(WR_VAR(0, 1, 2), 22); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.back().seti(222); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); s[0].seti(1); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0] = var(WR_VAR(0, 1, 192)); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); } }); // Test date matcher add_method("date", [](Fixture& f) { { auto m = get_matcher("yearmin=2000"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_i(WR_VAR(0, 4, 1), 1999); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0].seti(2000); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); } { auto m = get_matcher("yearmax=2000"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_i(WR_VAR(0, 4, 1), 2001); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0].seti(2000); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); } { auto m = get_matcher("yearmin=2000, yearmax=2010"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_i(WR_VAR(0, 4, 1), 1999); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0].seti(2011); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0].seti(2000); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); s[0].seti(2005); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); s[0].seti(2010); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); } }); // Test coordinates matcher add_method("coords", [](Fixture& f) { { auto m = get_matcher("latmin=45.00"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_d(WR_VAR(0, 5, 1), 43.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0].setd(45.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); s[0].setd(46.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); } { auto m = get_matcher("latmax=45.00"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_d(WR_VAR(0, 5, 1), 46.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0].setd(45.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); s[0].setd(44.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); } { auto m = get_matcher("lonmin=11.00, lonmax=180.0"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_d(WR_VAR(0, 6, 1), 10.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0].setd(11.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); s[0].setd(12.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); } { auto m = get_matcher("lonmin=-180, lonmax=11.0"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_d(WR_VAR(0, 6, 1), 12.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0].setd(11.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); s[0].setd(10.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); } { auto m = get_matcher("latmin=45.0, latmax=46.0, lonmin=10.0, lonmax=12.0"); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_d(WR_VAR(0, 5, 1), 45.5); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s.store_variable_d(WR_VAR(0, 6, 1), 13.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[1].setd(11.0); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); } }); // Test rep_memo matcher add_method("rep_memo", [](Fixture& f) { auto m = get_matcher("rep_memo=synop"); Tables tables; tables.load_bufr(BufrTableID(200, 0, 0, 14, 1)); Subset s(tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); wassert(s.store_variable_c(WR_VAR(0, 1, 194), "temp")); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_NO); s[0].setc("synop"); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); }); // Test empty matcher add_method("empty", [](Fixture& f) { std::unique_ptr m = Matcher::create(*Query::create()); Subset s(f.tables); wassert(actual_matcher_result(m->match(MatchedSubset(s))) == matcher::MATCH_YES); }); } } test1("core_match_wreport_subset"); struct FixtureBulletin : public dballe::tests::Fixture { BufrBulletin* bulletin = nullptr; ~FixtureBulletin() { delete bulletin; } BufrBulletin& get_bulletin() { delete bulletin; bulletin = BufrBulletin::create().release(); BufrBulletin& b = *bulletin; b.edition_number = 4; b.originating_centre = 200; b.originating_subcentre = 0; b.master_table_version_number = 14; b.master_table_version_number_local = 0; b.load_tables(); return b; } }; class TestBulletin : public FixtureTestCase { using FixtureTestCase::FixtureTestCase; void register_tests() override { // Test station_id matcher add_method("station_id", [](Fixture& f) { auto m = get_matcher("ana_id=1"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(1).store_variable_i(WR_VAR(0, 1, 1), 1); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_i(WR_VAR(0, 1, 192), 1); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); }); // Test station WMO matcher add_method("station_wmo", [](Fixture& f) { { auto m = get_matcher("block=11"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(1).store_variable_i(WR_VAR(0, 1, 1), 1); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(1).back().seti(11); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); b.obtain_subset(1).store_variable_i(WR_VAR(0, 1, 2), 222); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } { auto m = get_matcher("block=11, station=222"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_i(WR_VAR(0, 1, 1), 1); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).back().seti(11); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_i(WR_VAR(0, 1, 2), 22); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).back().seti(222); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); b.obtain_subset(0)[0].seti(1); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0)[0] = var(WR_VAR(0, 1, 192)); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); } // Valid block and station must be in the same subset { auto m = get_matcher("block=11, station=222"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_i(WR_VAR(0, 1, 1), 11); b.obtain_subset(1).store_variable_i(WR_VAR(0, 1, 2), 222); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_i(WR_VAR(0, 1, 2), 222); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } }); // Test date matcher add_method("date", [](Fixture& f) { { auto m = get_matcher("yearmin=2000"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_i(WR_VAR(0, 4, 1), 1999); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0)[0].seti(2000); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } { auto m = get_matcher("yearmax=2000"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_i(WR_VAR(0, 4, 1), 2001); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0)[0].seti(2000); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } { auto m = get_matcher("yearmin=2000, yearmax=2010"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_i(WR_VAR(0, 4, 1), 1999); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0)[0].seti(2011); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0)[0].seti(2000); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); b.obtain_subset(0)[0].seti(2005); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); b.obtain_subset(0)[0].seti(2010); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } }); // Test coordinates matcher add_method("coords", [](Fixture& f) { { auto m = get_matcher("latmin=45.0"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(1).store_variable_d(WR_VAR(0, 5, 1), 43.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(1)[0].setd(45.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); b.obtain_subset(1)[0].setd(46.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } { auto m = get_matcher("latmax=45.0"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(1).store_variable_d(WR_VAR(0, 5, 1), 46.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(1)[0].setd(45.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); b.obtain_subset(1)[0].setd(44.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } { auto m = get_matcher("lonmin=11.00, lonmax=180.0"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_d(WR_VAR(0, 6, 1), 10.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0)[0].setd(11.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); b.obtain_subset(0)[0].setd(12.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } { auto m = get_matcher("lonmin=-180, lonmax=11.0"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_d(WR_VAR(0, 6, 1), 12.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0)[0].setd(11.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); b.obtain_subset(0)[0].setd(10.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } { auto m = get_matcher("latmin=45.0, latmax=46.0, lonmin=10.0, lonmax=12.0"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_d(WR_VAR(0, 5, 1), 45.5); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_d(WR_VAR(0, 6, 1), 13.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0)[1].setd(11.0); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); } }); // Test rep_memo matcher add_method("rep_memo", [](Fixture& f) { auto m = get_matcher("rep_memo=synop"); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0).store_variable_c(WR_VAR(0, 1, 194), "temp"); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_NO); b.obtain_subset(0)[0].setc("synop"); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); }); // Test empty matcher add_method("empty", [](Fixture& f) { std::unique_ptr m = Matcher::create(*Query::create()); BufrBulletin& b = f.get_bulletin(); wassert(actual_matcher_result(m->match(MatchedBulletin(b))) == matcher::MATCH_YES); }); } } test2("core_match_wreport_bulletin"); } dballe-7.7/dballe/core/file.cc0000644000175000017500000000355312652630043013143 00000000000000#include "file.h" #include #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace core { File::File(const std::string& name, FILE* fd, bool close_on_exit) : m_name(name), fd(fd), close_on_exit(close_on_exit), idx(0) { } File::~File() { if (fd && close_on_exit) fclose(fd); } bool File::foreach(std::function dest) { while (true) { if (auto bm = read()) { if (!dest(bm)) return false; } else break; } return true; } std::string File::resolve_test_data_file(const std::string& name) { // Skip appending the test data path for pathnames starting with ./ if (name[0] == '.') return name; const char* testdatadirenv = getenv("DBA_TESTDATA"); std::string testdatadir = testdatadirenv ? testdatadirenv : "."; return testdatadir + "/" + name; } std::unique_ptr File::open_test_data_file(Encoding type, const std::string& name) { return File::create(type, resolve_test_data_file(name), "r"); } BinaryMessage BufrFile::read() { BinaryMessage res(BUFR); if (BufrBulletin::read(fd, res.data, m_name.c_str(), &res.offset)) { res.pathname = m_name; res.index = idx++; return res; } return BinaryMessage(BUFR); } void BufrFile::write(const std::string& msg) { BufrBulletin::write(msg, fd, m_name.c_str()); } BinaryMessage CrexFile::read() { BinaryMessage res(CREX); if (CrexBulletin::read(fd, res.data, m_name.c_str(), &res.offset)) { res.pathname = m_name; res.index = idx++; return res; } return BinaryMessage(CREX); } void CrexFile::write(const std::string& msg) { CrexBulletin::write(msg, fd, m_name.c_str()); } } } dballe-7.7/dballe/core/trace.h0000644000175000017500000000252012652630043013155 00000000000000/* * core/trace - Debugging trace functions * * Copyright (C) 2005--2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_CORE_TRACE_H #define DBALLE_CORE_TRACE_H /** * Include this file if you want to enable trace functions in a source * * The trace functions are not compiled unless you #define TRACE_SOURCE * before including this header. */ #ifdef TRACE_SOURCE #include // Output a trace message #define TRACE(...) fprintf(stderr, __VA_ARGS__) // Prefix a block of code to compile only if trace is enabled #define IFTRACE if (1) #else #define TRACE(...) do { } while (0) #define IFTRACE if (0) #endif #endif dballe-7.7/dballe/core/query-test.cc0000644000175000017500000001773712652630043014357 00000000000000#include "core/tests.h" #include "core/query.h" #include "core/record.h" #include using namespace std; using namespace dballe; using namespace dballe::tests; using namespace wreport; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("all_unset", []() { core::Query q; wassert(actual(q.ana_id) == MISSING_INT); wassert(actual(q.prio_min) == MISSING_INT); wassert(actual(q.prio_max) == MISSING_INT); wassert(actual(q.rep_memo) == ""); wassert(actual(q.mobile) == MISSING_INT); wassert(actual(q.ident.is_missing()).istrue()); wassert(actual(q.latrange) == LatRange()); wassert(actual(q.lonrange) == LonRange()); wassert(actual(q.datetime) == DatetimeRange()); wassert(actual(q.level) == Level()); wassert(actual(q.trange) == Trange()); wassert(actual(q.varcodes.size()) == 0); wassert(actual(q.query) == ""); wassert(actual(q.ana_filter) == ""); wassert(actual(q.data_filter) == ""); wassert(actual(q.attr_filter) == ""); wassert(actual(q.limit) == MISSING_INT); wassert(actual(q.block) == MISSING_INT); wassert(actual(q.station) == MISSING_INT); }); add_method("all_set", []() { core::Record rec; rec.set("ana_id", 4); rec.set("priority", 1); rec.set("rep_memo", "foo"); rec.set("mobile", 0); rec.set("ident", "bar"); rec.set("lat", 44.123); rec.set("lon", 11.123); rec.set(Datetime(2000, 1, 2, 12, 30, 45)); rec.set(Level(10, 11, 12, 13)); rec.set(Trange(20, 21, 22)); rec.set("var", "B12101"); rec.set("query", "best"); rec.set("ana_filter", "B01001=1"); rec.set("data_filter", "B12101>260"); rec.set("attr_filter", "B33007>50"); rec.set("limit", 100); rec.set("block", 16); rec.set("station", 404); core::Query q; q.set_from_record(rec); wassert(actual(q.ana_id) == 4); wassert(actual(q.prio_min) == 1); wassert(actual(q.prio_max) == 1); wassert(actual(q.rep_memo) == "foo"); wassert(actual(q.mobile) == 0); wassert(actual(q.ident.is_missing()).isfalse()); wassert(actual(q.ident.get()) == "bar"); wassert(actual(q.latrange) == LatRange(44.123, 44.123)); wassert(actual(q.lonrange) == LonRange(11.123, 11.123)); wassert(actual(q.datetime) == DatetimeRange(2000, 1, 2, 12, 30, 45, 2000, 1, 2, 12, 30, 45)); wassert(actual(q.level) == Level(10, 11, 12, 13)); wassert(actual(q.trange) == Trange(20, 21, 22)); wassert(actual(q.varcodes.size()) == 1); wassert(actual(*q.varcodes.begin()) == WR_VAR(0, 12, 101)); wassert(actual(q.query) == "best"); wassert(actual(q.ana_filter) == "B01001=1"); wassert(actual(q.data_filter) == "B12101>260"); wassert(actual(q.attr_filter) == "B33007>50"); wassert(actual(q.limit) == 100); wassert(actual(q.block) == 16); wassert(actual(q.station) == 404); }); add_method("prio", []() { core::Query q; q.set_from_test_string("priority=11"); wassert(actual(q.prio_min) == 11); wassert(actual(q.prio_max) == 11); q.clear(); q.set_from_test_string("priomin=12"); wassert(actual(q.prio_min) == 12); wassert(actual(q.prio_max) == MISSING_INT); q.clear(); q.set_from_test_string("priomax=12"); wassert(actual(q.prio_min) == MISSING_INT); wassert(actual(q.prio_max) == 12); q.clear(); q.set_from_test_string("priomin=11, priomax=22"); wassert(actual(q.prio_min) == 11); wassert(actual(q.prio_max) == 22); q.clear(); q.set_from_test_string("priomin=11, priomax=22, priority=16"); wassert(actual(q.prio_min) == 16); wassert(actual(q.prio_max) == 16); }); add_method("lat", []() { core::Query q; q.set_from_test_string("lat=45.0"); wassert(actual(q.latrange) == LatRange(45.0, 45.0)); q.clear(); q.set_from_test_string("latmin=45.0"); wassert(actual(q.latrange) == LatRange(45.0, LatRange::DMAX)); q.clear(); q.set_from_test_string("latmax=45.0"); wassert(actual(q.latrange) == LatRange(LatRange::DMIN, 45.0)); q.clear(); q.set_from_test_string("latmin=40.0, latmax=50.0"); wassert(actual(q.latrange) == LatRange(40.0, 50.0)); q.clear(); q.set_from_test_string("latmin=40.0, latmax=50.0, lat=42.0"); wassert(actual(q.latrange) == LatRange(42.0, 42.0)); }); add_method("lon", []() { core::Query q; q.set_from_test_string("lon=45.0"); wassert(actual(q.lonrange) == LonRange(45.0, 45.0)); q.clear(); try { q.set_from_test_string("lonmin=45.0"); wassert(actual(false).istrue()); } catch (std::exception& e) { wassert(actual(e.what()).contains("open ended range")); } wassert(actual(q.lonrange) == LonRange()); q.clear(); q.set_from_test_string("lonmin=40.0, lonmax=50.0"); wassert(actual(q.lonrange) == LonRange(40.0, 50.0)); q.clear(); q.set_from_test_string("lonmin=40.0, lonmax=50.0, lon=42.0"); wassert(actual(q.lonrange) == LonRange(42.0, 42.0)); }); add_method("datetime", []() { core::Query q; q.set_from_test_string("year=2015"); wassert(actual(q.datetime) == DatetimeRange(2015, 1, 1, 0 , 0, 0, 2015, 12, 31, 23, 59, 59)); q.clear(); q.set_from_test_string("year=2015, monthmin=1, monthmax=2"); wassert(actual(q.datetime) == DatetimeRange(2015, 1, 1, 0 , 0, 0, 2015, 2, 28, 23, 59, 59)); q.clear(); q.set_from_test_string("year=2015, monthmin=2, day=28"); wassert(actual(q.datetime) == DatetimeRange(2015, 2, 28, 0 , 0, 0, 2015, 12, 28, 23, 59, 59)); q.clear(); q.set_from_test_string("yearmin=2000, yearmax=2012, month=2, min=30"); wassert(actual(q.datetime) == DatetimeRange(2000, 2, 1, 0, 30, 0, 2012, 2, 29, 23, 30, 59)); q.clear(); q.set_from_test_string("yearmin=2010, yearmax=2012, year=2000, month=2, min=30"); wassert(actual(q.datetime) == DatetimeRange(2000, 2, 1, 0, 30, 0, 2000, 2, 29, 23, 30, 59)); }); add_method("varlist", []() { core::Query q; q.set_from_test_string("var=B12101"); wassert(actual(q.varcodes.size()) == 1); wassert(actual(*q.varcodes.begin()) == WR_VAR(0, 12, 101)); q.clear(); q.set_from_test_string("varlist=B12101,B01001"); wassert(actual(q.varcodes.size()) == 2); wassert(actual(*q.varcodes.begin()) == WR_VAR(0, 1, 1)); wassert(actual(*q.varcodes.rbegin()) == WR_VAR(0, 12, 101)); q.clear(); q.set_from_test_string("varlist=B12101,B01001, var=B12102"); wassert(actual(q.varcodes.size()) == 1); wassert(actual(*q.varcodes.begin()) == WR_VAR(0, 12, 102)); }); add_method("modifiers", []() { wassert(actual(core::Query::parse_modifiers("best")) == DBA_DB_MODIFIER_BEST); wassert(actual(core::Query::parse_modifiers("details")) == DBA_DB_MODIFIER_SUMMARY_DETAILS); }); } } test("core_query"); } dballe-7.7/dballe/msg/0000755000175000017500000000000012653425050011626 500000000000000dballe-7.7/dballe/msg/msg.h0000644000175000017500000003675112652630043012520 00000000000000/* * dballe/msg - Hold an interpreted weather bulletin * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBA_MSG_H #define DBA_MSG_H /** @file * @ingroup msg * * Abstraction for a weather report message which is independent from the * encoding, used to make sense of decoded information and to carry data between * the various import and export modules of DB-ALLe. * * The internal representation is as connected as possible to physics rather than * to observations. dba_msg is a container for related weather information, * stored in a nonambiguous way. * * To understand what is the difference betwee ::dba_msg and other ways of * representing weather data, it is important to keep in mind how a value is * usually defined in the various encodings: * * \li by previous values and position, as in the AOF encoding * \li by previous values, data descriptor and sometimes position, as in the BUFR * encoding * \li by measure type and physical coordinates, as in ::dba_msg and the DB-ALLe * database * * ::dba_msg contains values as tuples (variable, level layer, time range). * * The variable is represented by a dba_var. The dba_varcode of the dba_var * refers to a local B table which lists physical measurements unambiguously. * * Level layer is a triple (level type, l1, l2) and time range is a triple * (pindicator, p1, p2). The values of these two triples follow what is used in * the GRIB encoding plus some local extensions, and an explanation of their * possible value is found in the document "DB-ALLe Guide of the Fortran API". * * Importers and exporters have to implement a mapping between their * representation and the unambiguous physical representation. Luckily this is * necessarily possible, because the ultimate purpose of the various message * encodings is to correctly transmit those physical data. * * Since to work with the full physical coordinates one needs to specify a lot of * different parameters in order to identify a value (BLocal value, level layer, * time range), there is a var.h module available with shortcut functions to * the values that are used more commonly. */ #include #include #include #include #include #include #include #include #include struct lua_State; namespace dballe { struct Record; struct CSVReader; namespace msg { struct Context; /** * Read data from a CSV input. * * Reading stops when Report changes. */ Messages messages_from_csv(CSVReader& in); /** * Output in CSV format */ void messages_to_csv(const Messages& msgs, std::ostream& out); } /** * Source of the data */ enum MsgType { MSG_GENERIC, /**< Data from unspecified source */ MSG_SYNOP, /**< Synop measured data */ MSG_PILOT, /**< Pilot sounding data */ MSG_TEMP, /**< Temp sounding data */ MSG_TEMP_SHIP, /**< Temp ship sounding data */ MSG_AIREP, /**< Airep airplane data */ MSG_AMDAR, /**< Amdar airplane data */ MSG_ACARS, /**< Acars airplane data */ MSG_SHIP, /**< Ship measured data */ MSG_BUOY, /**< Buoy measured data */ MSG_METAR, /**< Metar data */ MSG_SAT, /**< Satellite data */ MSG_POLLUTION /**< Pollution data */ }; /** * Return a string with the name of a dba_msg_type * * @param type * The dba_msg_type value to name * @return * The name, as a const string. This function is thread safe. */ const char* msg_type_name(MsgType type); /** * Storage for related physical data */ class Msg : public Message { protected: /** * Return the index of the given context, or -1 if it was not found */ int find_index(const Level& lev, const Trange& tr) const; /// Sensor network of origin of the Msg contents std::string m_network; /// Reference coordinates for the Msg contents Coords m_coords; /// Identifier of the contents originator Ident m_ident; /// Reference time for the Msg contents Datetime m_datetime; public: /// Source of the data MsgType type; /** Context in the message */ std::vector data; /** * Create a new dba_msg * * By default, type is MSG_GENERIC */ Msg(); ~Msg(); Msg(const Msg& m); Msg& operator=(const Msg& m); /** * Return a reference to \a o downcasted as a Msg. * * Throws an exception if \a o is not a Msg. */ static const Msg& downcast(const Message& o); /** * Return a reference to \a o downcasted as a Msg. * * Throws an exception if \a o is not a Msg. */ static Msg& downcast(Message& o); std::unique_ptr clone() const override; Datetime get_datetime() const override { return m_datetime; } const wreport::Var* get(wreport::Varcode code, const Level& lev, const Trange& tr) const override; void print(FILE* out) const override; unsigned diff(const Message& msg) const override; void set_datetime(const Datetime& dt) { m_datetime = dt; } /// Remove all information from Msg void clear(); /** * Add a missing context, taking care of its memory management * * Note: if the context already exists, an exception is thrown */ void add_context(std::unique_ptr&& ctx); /** * Remove a context from the message * * @return true if the context was removed, false if it did not exist */ bool remove_context(const Level& lev, const Trange& tr); /** * Find a msg::Context given its description * * @param lev * The Level to query * @param tr * The Trange to query * @return * The context found, or NULL if it was not found. */ const msg::Context* find_context(const Level& lev, const Trange& tr) const; /** * Find the station info context * * @return * The context found, or NULL if it was not found. */ const msg::Context* find_station_context() const; /** * Find a msg::Context given its description * * @param lev * The Level to query * @param tr * The Trange to query * @return * The context found, or NULL if it was not found. */ msg::Context* edit_context(const Level& lev, const Trange& tr); /** * Find a msg::Context given its description, creating it if it does not * exist * * @param lev * The Level to query * @param tr * The Trange to query * @return * The context found */ msg::Context& obtain_context(const Level& lev, const Trange& tr); /// Shortcut to obtain_context(Level(), Trange()); msg::Context& obtain_station_context(); /** * Find a variable given its description * * @param code * The ::dba_varcode of the variable to query. See @ref vartable.h * @param lev * The Level to query * @param tr * The Trange to query * @return * The variable found, or NULL if it was not found. */ wreport::Var* edit(wreport::Varcode code, const Level& lev, const Trange& tr); /** * Remove a variable given its description * * @param code * The ::dba_varcode of the variable to query. See @ref vartable.h * @param lev * The Level to query * @param tr * The Trange to query * @returns * True if the variable was removed, false if it was not found. */ bool remove(wreport::Varcode code, const Level& lev, const Trange& tr); /** * Find a datum given its shortcut ID * * @param msg * The message to query * @param id * Shortcut ID of the value to set (see @ref vars.h) * @return * The value found, or NULL if it was not found. */ const wreport::Var* find_by_id(int id) const; /** * Find a contexts given level and timerange found in a shortcut ID * * @param msg * The message to query * @param id * Shortcut ID with the level information to use * @return * The context found, or NULL if it was not found. */ const msg::Context* find_context_by_id(int id) const; /** * Find a datum given its shortcut ID * * @param msg * The message to query * @param id * Shortcut ID of the value to set (see @ref vars.h) * @return * The value found, or NULL if it was not found. */ wreport::Var* edit_by_id(int id); /** * Add or replace a value * * @param var * The Var with the value to set * @param code * The dba_varcode of the destination value. If it is different than the * varcode of var, a conversion will be attempted. * @param lev * The Level of the value * @param tr * The Trange of the value */ void set(const wreport::Var& var, wreport::Varcode code, const Level& lev, const Trange& tr); /** * Add or replace a value * * @param var * The Var with the value to set * @param shortcut * Shortcut ID of the value to set */ void set_by_id(const wreport::Var& var, int shortcut); /** * Add or replace a value, taking ownership of the source variable without * copying it. * * @param msg * The Var with the value to set. This Msg will take ownership of memory * management. * @param lev * The Level of the value * @param tr * The Trange of the value */ void set(std::unique_ptr&& var, const Level& lev, const Trange& tr); /** * Add or replace an integer value in the dba_msg * * @param code * The dba_varcode of the destination value.. See @ref vartable.h * @param val * The integer value of the data * @param conf * The confidence interval of the data, as the value of a B33007 WMO B (per * cent confidence) table entry, that is, a number between 0 and 100 * inclusive. -1 means no confidence interval attribute. * @param lev * The Level of the value * @param tr * The Trange of the value */ void seti(wreport::Varcode code, int val, int conf, const Level& lev, const Trange& tr); /** * Add or replace a double value in the dba_msg * * @param code * The dba_varcode of the destination value. See @ref vartable.h * @param val * The double value of the data * @param conf * The confidence interval of the data, as the value of a B33007 WMO B (per * cent confidence) table entry, that is, a number between 0 and 100 * inclusive. -1 means no confidence interval attribute. * @param lev * The Level of the value * @param tr * The Trange of the value */ void setd(wreport::Varcode code, double val, int conf, const Level& lev, const Trange& tr); /** * Add or replace a string value in the dba_msg * * @param code * The dba_varcode of the destination value. See @ref vartable.h * @param val * The string value of the data * @param conf * The confidence interval of the data, as the value of a B33007 WMO B (per * cent confidence) table entry, that is, a number between 0 and 100 * inclusive. -1 means no confidence interval attribute. * @param lev * The Level of the value * @param tr * The Trange of the value */ void setc(wreport::Varcode code, const char* val, int conf, const Level& lev, const Trange& tr); /** * Copy to dest all the variable in this message that match \a filter * TODO: to be implemented */ //void filter(const Record& filter, Msg& dest) const; /** * Copy a Msg, removing the sounding significance from the level * descriptions and packing together the data at the same pressure level. * * This is used to postprocess data after decoding, where the l2 field of the * level description is temporarily used to store the vertical sounding * significance, to simplify decoding. */ void sounding_pack_levels(Msg& dst) const; #if 0 /** * Copy a Msg, adding the sounding significance from the level descriptions * and moving the data at the same pressure level to the resulting * pseudolevels. * * This is used to preprocess data before encoding, where the l2 field of the * level description is temporarily used to store the vertical sounding * significance, to simplify encoding. */ void sounding_unpack_levels(Msg& dst) const; #endif /** * Read data from a CSV input. * * Reading stops when one of Longitude, Latitude, Report or Date changes. * * @return true if some CSV data has been found, false on EOF */ bool from_csv(CSVReader& in); /** * Output in CSV format */ void to_csv(std::ostream& out) const; /// Output the CSV header static void csv_header(std::ostream& out); /** * Get the message source type corresponding to the given report code */ static MsgType type_from_repmemo(const char* repmemo); /** * Get the report code corresponding to the given message source type */ static const char* repmemo_from_type(MsgType type); #include /** * Push the variable as an object in the lua stack */ void lua_push(struct lua_State* L); /** * Check that the element at \a idx is a dba_msg * * @return the dba_msg element, or NULL if the check failed */ static Msg* lua_check(struct lua_State* L, int idx); }; /** * Match adapter for Msg */ struct MatchedMsg : public Matched { const Msg& m; MatchedMsg(const Msg& r); ~MatchedMsg(); matcher::Result match_var_id(int val) const override; matcher::Result match_station_id(int val) const override; matcher::Result match_station_wmo(int block, int station=-1) const override; matcher::Result match_datetime(const DatetimeRange& range) const override; matcher::Result match_coords(const LatRange& latrange, const LonRange& lonrange) const override; matcher::Result match_rep_memo(const char* memo) const override; }; /** * Match adapter for Messages */ struct MatchedMessages : public Matched { const Messages& m; MatchedMessages(const Messages& m); ~MatchedMessages(); matcher::Result match_var_id(int val) const override; matcher::Result match_station_id(int val) const override; matcher::Result match_station_wmo(int block, int station=-1) const override; matcher::Result match_datetime(const DatetimeRange& range) const override; matcher::Result match_coords(const LatRange& latrange, const LonRange& lonrange) const override; matcher::Result match_rep_memo(const char* memo) const override; }; } #endif dballe-7.7/dballe/msg/context-extravars.h0000644000175000017500000007274212652630120015427 00000000000000/** Set the value of "WMO block number" from a variable of type int */ inline void set_block(int val) { seti(WR_VAR(0, 1, 1), val); } /** Get the "WMO block number" physical value stored in the message */ inline const wreport::Var* get_block() const { return find(WR_VAR(0, 1, 1)); } /** Set the value of "WMO station number" from a variable of type int */ inline void set_station(int val) { seti(WR_VAR(0, 1, 2), val); } /** Get the "WMO station number" physical value stored in the message */ inline const wreport::Var* get_station() const { return find(WR_VAR(0, 1, 2)); } /** Set the value of "Aircraft registration number or other identification" from a variable of type const char* */ inline void set_flight_reg_no(const char* val) { setc(WR_VAR(0, 1, 8), val); } /** Get the "Aircraft registration number or other identification" physical value stored in the message */ inline const wreport::Var* get_flight_reg_no() const { return find(WR_VAR(0, 1, 8)); } /** Set the value of "Mobile station identifier" from a variable of type const char* */ inline void set_ident(const char* val) { setc(WR_VAR(0, 1, 11), val); } /** Get the "Mobile station identifier" physical value stored in the message */ inline const wreport::Var* get_ident() const { return find(WR_VAR(0, 1, 11)); } /** Set the value of "Station or site name" from a variable of type const char* */ inline void set_st_name(const char* val) { setc(WR_VAR(0, 1, 19), val); } /** Get the "Station or site name" physical value stored in the message */ inline const wreport::Var* get_st_name() const { return find(WR_VAR(0, 1, 19)); } /** Set the value of "ICAO location indicator" from a variable of type const char* */ inline void set_st_name_icao(const char* val) { setc(WR_VAR(0, 1, 63), val); } /** Get the "ICAO location indicator" physical value stored in the message */ inline const wreport::Var* get_st_name_icao() const { return find(WR_VAR(0, 1, 63)); } /** Set the value of "Report mnemonic" from a variable of type const char* */ inline void set_rep_memo(const char* val) { setc(WR_VAR(0, 1, 194), val); } /** Get the "Report mnemonic" physical value stored in the message */ inline const wreport::Var* get_rep_memo() const { return find(WR_VAR(0, 1, 194)); } /** Set the value of "Air quality observing station local code" from a variable of type int */ inline void set_poll_lcode(int val) { seti(WR_VAR(0, 1, 212), val); } /** Get the "Air quality observing station local code" physical value stored in the message */ inline const wreport::Var* get_poll_lcode() const { return find(WR_VAR(0, 1, 212)); } /** Set the value of "Airbase air quality observing station code" from a variable of type int */ inline void set_poll_scode(int val) { seti(WR_VAR(0, 1, 213), val); } /** Get the "Airbase air quality observing station code" physical value stored in the message */ inline const wreport::Var* get_poll_scode() const { return find(WR_VAR(0, 1, 213)); } /** Set the value of "GEMS air quality observing station code" from a variable of type int */ inline void set_poll_gemscode(int val) { seti(WR_VAR(0, 1, 214), val); } /** Get the "GEMS air quality observing station code" physical value stored in the message */ inline const wreport::Var* get_poll_gemscode() const { return find(WR_VAR(0, 1, 214)); } /** Set the value of "Air quality observing station dominant emission source" from a variable of type int */ inline void set_poll_source(int val) { seti(WR_VAR(0, 1, 215), val); } /** Get the "Air quality observing station dominant emission source" physical value stored in the message */ inline const wreport::Var* get_poll_source() const { return find(WR_VAR(0, 1, 215)); } /** Set the value of "Air quality observing station area type" from a variable of type int */ inline void set_poll_atype(int val) { seti(WR_VAR(0, 1, 216), val); } /** Get the "Air quality observing station area type" physical value stored in the message */ inline const wreport::Var* get_poll_atype() const { return find(WR_VAR(0, 1, 216)); } /** Set the value of "Air quality observing station terrain type" from a variable of type int */ inline void set_poll_ttype(int val) { seti(WR_VAR(0, 1, 217), val); } /** Get the "Air quality observing station terrain type" physical value stored in the message */ inline const wreport::Var* get_poll_ttype() const { return find(WR_VAR(0, 1, 217)); } /** Set the value of "Type of station" from a variable of type int */ inline void set_st_type(int val) { seti(WR_VAR(0, 2, 1), val); } /** Get the "Type of station" physical value stored in the message */ inline const wreport::Var* get_st_type() const { return find(WR_VAR(0, 2, 1)); } /** Set the value of "Type of instrumentation for wind measurement" from a variable of type int */ inline void set_wind_inst(int val) { seti(WR_VAR(0, 2, 2), val); } /** Get the "Type of instrumentation for wind measurement" physical value stored in the message */ inline const wreport::Var* get_wind_inst() const { return find(WR_VAR(0, 2, 2)); } /** Set the value of "Precision of temperature observation" from a variable of type double */ inline void set_temp_precision(double val) { setd(WR_VAR(0, 2, 5), val); } /** Get the "Precision of temperature observation" physical value stored in the message */ inline const wreport::Var* get_temp_precision() const { return find(WR_VAR(0, 2, 5)); } /** Set the value of "Aircraft navigational system" from a variable of type int */ inline void set_navsys(int val) { seti(WR_VAR(0, 2, 61), val); } /** Get the "Aircraft navigational system" physical value stored in the message */ inline const wreport::Var* get_navsys() const { return find(WR_VAR(0, 2, 61)); } /** Set the value of "Aircraft data relay system" from a variable of type int */ inline void set_data_relay(int val) { seti(WR_VAR(0, 2, 62), val); } /** Get the "Aircraft data relay system" physical value stored in the message */ inline const wreport::Var* get_data_relay() const { return find(WR_VAR(0, 2, 62)); } /** Set the value of "Aircraft roll angle" from a variable of type double */ inline void set_flight_roll(double val) { setd(WR_VAR(0, 2, 63), val); } /** Get the "Aircraft roll angle" physical value stored in the message */ inline const wreport::Var* get_flight_roll() const { return find(WR_VAR(0, 2, 63)); } /** Set the value of "Original specification of latitude/longitude" from a variable of type int */ inline void set_latlon_spec(int val) { seti(WR_VAR(0, 2, 70), val); } /** Get the "Original specification of latitude/longitude" physical value stored in the message */ inline const wreport::Var* get_latlon_spec() const { return find(WR_VAR(0, 2, 70)); } /** Set the value of "Year of the observation" from a variable of type int */ inline void set_year(int val) { seti(WR_VAR(0, 4, 1), val); } /** Get the "Year of the observation" physical value stored in the message */ inline const wreport::Var* get_year() const { return find(WR_VAR(0, 4, 1)); } /** Set the value of "Month of the observation" from a variable of type int */ inline void set_month(int val) { seti(WR_VAR(0, 4, 2), val); } /** Get the "Month of the observation" physical value stored in the message */ inline const wreport::Var* get_month() const { return find(WR_VAR(0, 4, 2)); } /** Set the value of "Day of the observation" from a variable of type int */ inline void set_day(int val) { seti(WR_VAR(0, 4, 3), val); } /** Get the "Day of the observation" physical value stored in the message */ inline const wreport::Var* get_day() const { return find(WR_VAR(0, 4, 3)); } /** Set the value of "Hour of the observation" from a variable of type int */ inline void set_hour(int val) { seti(WR_VAR(0, 4, 4), val); } /** Get the "Hour of the observation" physical value stored in the message */ inline const wreport::Var* get_hour() const { return find(WR_VAR(0, 4, 4)); } /** Set the value of "Minute of the observation" from a variable of type int */ inline void set_minute(int val) { seti(WR_VAR(0, 4, 5), val); } /** Get the "Minute of the observation" physical value stored in the message */ inline const wreport::Var* get_minute() const { return find(WR_VAR(0, 4, 5)); } /** Set the value of "Second of the observation" from a variable of type int */ inline void set_second(int val) { seti(WR_VAR(0, 4, 6), val); } /** Get the "Second of the observation" physical value stored in the message */ inline const wreport::Var* get_second() const { return find(WR_VAR(0, 4, 6)); } /** Set the value of "Latitude of the station" from a variable of type double */ inline void set_latitude(double val) { setd(WR_VAR(0, 5, 1), val); } /** Get the "Latitude of the station" physical value stored in the message */ inline const wreport::Var* get_latitude() const { return find(WR_VAR(0, 5, 1)); } /** Set the value of "Longiture of the station" from a variable of type double */ inline void set_longitude(double val) { setd(WR_VAR(0, 6, 1), val); } /** Get the "Longiture of the station" physical value stored in the message */ inline const wreport::Var* get_longitude() const { return find(WR_VAR(0, 6, 1)); } /** Set the value of "Isobaric surface" from a variable of type double */ inline void set_isobaric_surface(double val) { setd(WR_VAR(0, 7, 4), val); } /** Get the "Isobaric surface" physical value stored in the message */ inline const wreport::Var* get_isobaric_surface() const { return find(WR_VAR(0, 7, 4)); } /** Set the value of "Height of release of sonde above msl" from a variable of type double */ inline void set_height_release(double val) { setd(WR_VAR(0, 7, 7), val); } /** Get the "Height of release of sonde above msl" physical value stored in the message */ inline const wreport::Var* get_height_release() const { return find(WR_VAR(0, 7, 7)); } /** Set the value of "Height of station" from a variable of type double */ inline void set_height_station(double val) { setd(WR_VAR(0, 7, 30), val); } /** Get the "Height of station" physical value stored in the message */ inline const wreport::Var* get_height_station() const { return find(WR_VAR(0, 7, 30)); } /** Set the value of "Height of barometer above mean sea level" from a variable of type double */ inline void set_height_baro(double val) { setd(WR_VAR(0, 7, 31), val); } /** Get the "Height of barometer above mean sea level" physical value stored in the message */ inline const wreport::Var* get_height_baro() const { return find(WR_VAR(0, 7, 31)); } /** Set the value of "Phase of aircraft flight" from a variable of type int */ inline void set_flight_phase(int val) { seti(WR_VAR(0, 8, 4), val); } /** Get the "Phase of aircraft flight" physical value stored in the message */ inline const wreport::Var* get_flight_phase() const { return find(WR_VAR(0, 8, 4)); } /** Set the value of "Time significance" from a variable of type int */ inline void set_timesig(int val) { seti(WR_VAR(0, 8, 21), val); } /** Get the "Time significance" physical value stored in the message */ inline const wreport::Var* get_timesig() const { return find(WR_VAR(0, 8, 21)); } /** Set the value of "Station elevation quality mark (for mobile stations)" from a variable of type int */ inline void set_station_height_quality(int val) { seti(WR_VAR(0, 33, 24), val); } /** Get the "Station elevation quality mark (for mobile stations)" physical value stored in the message */ inline const wreport::Var* get_station_height_quality() const { return find(WR_VAR(0, 33, 24)); } /** Set the value of "Total cloud cover (N)" from a variable of type int */ inline void set_cloud_n(int val) { seti(WR_VAR(0, 20, 10), val); } /** Get the "Total cloud cover (N)" physical value stored in the message */ inline const wreport::Var* get_cloud_n() const { return find(WR_VAR(0, 20, 10)); } /** Set the value of "Cloud amount (N4)" from a variable of type int */ inline void set_cloud_n4(int val) { seti(WR_VAR(0, 20, 11), val); } /** Get the "Cloud amount (N4)" physical value stored in the message */ inline const wreport::Var* get_cloud_n4() const { return find(WR_VAR(0, 20, 11)); } /** Set the value of "Cloud amount (C4)" from a variable of type int */ inline void set_cloud_c4(int val) { seti(WR_VAR(0, 20, 12), val); } /** Get the "Cloud amount (C4)" physical value stored in the message */ inline const wreport::Var* get_cloud_c4() const { return find(WR_VAR(0, 20, 12)); } /** Set the value of "Height of base of cloud (H4)" from a variable of type double */ inline void set_cloud_h4(double val) { setd(WR_VAR(0, 20, 13), val); } /** Get the "Height of base of cloud (H4)" physical value stored in the message */ inline const wreport::Var* get_cloud_h4() const { return find(WR_VAR(0, 20, 13)); } /** Set the value of "Cloud amount (N3)" from a variable of type int */ inline void set_cloud_n3(int val) { seti(WR_VAR(0, 20, 11), val); } /** Get the "Cloud amount (N3)" physical value stored in the message */ inline const wreport::Var* get_cloud_n3() const { return find(WR_VAR(0, 20, 11)); } /** Set the value of "Cloud amount (C3)" from a variable of type int */ inline void set_cloud_c3(int val) { seti(WR_VAR(0, 20, 12), val); } /** Get the "Cloud amount (C3)" physical value stored in the message */ inline const wreport::Var* get_cloud_c3() const { return find(WR_VAR(0, 20, 12)); } /** Set the value of "Height of base of cloud (H3)" from a variable of type double */ inline void set_cloud_h3(double val) { setd(WR_VAR(0, 20, 13), val); } /** Get the "Height of base of cloud (H3)" physical value stored in the message */ inline const wreport::Var* get_cloud_h3() const { return find(WR_VAR(0, 20, 13)); } /** Set the value of "Cloud amount (N2)" from a variable of type int */ inline void set_cloud_n2(int val) { seti(WR_VAR(0, 20, 11), val); } /** Get the "Cloud amount (N2)" physical value stored in the message */ inline const wreport::Var* get_cloud_n2() const { return find(WR_VAR(0, 20, 11)); } /** Set the value of "Cloud amount (C2)" from a variable of type int */ inline void set_cloud_c2(int val) { seti(WR_VAR(0, 20, 12), val); } /** Get the "Cloud amount (C2)" physical value stored in the message */ inline const wreport::Var* get_cloud_c2() const { return find(WR_VAR(0, 20, 12)); } /** Set the value of "Height of base of cloud (H2)" from a variable of type double */ inline void set_cloud_h2(double val) { setd(WR_VAR(0, 20, 13), val); } /** Get the "Height of base of cloud (H2)" physical value stored in the message */ inline const wreport::Var* get_cloud_h2() const { return find(WR_VAR(0, 20, 13)); } /** Set the value of "Cloud amount (N1)" from a variable of type int */ inline void set_cloud_n1(int val) { seti(WR_VAR(0, 20, 11), val); } /** Get the "Cloud amount (N1)" physical value stored in the message */ inline const wreport::Var* get_cloud_n1() const { return find(WR_VAR(0, 20, 11)); } /** Set the value of "Cloud amount (C1)" from a variable of type int */ inline void set_cloud_c1(int val) { seti(WR_VAR(0, 20, 12), val); } /** Get the "Cloud amount (C1)" physical value stored in the message */ inline const wreport::Var* get_cloud_c1() const { return find(WR_VAR(0, 20, 12)); } /** Set the value of "Height of base of cloud (H1)" from a variable of type double */ inline void set_cloud_h1(double val) { setd(WR_VAR(0, 20, 13), val); } /** Get the "Height of base of cloud (H1)" physical value stored in the message */ inline const wreport::Var* get_cloud_h1() const { return find(WR_VAR(0, 20, 13)); } /** Set the value of "Cloud type (CH)" from a variable of type int */ inline void set_cloud_ch(int val) { seti(WR_VAR(0, 20, 12), val); } /** Get the "Cloud type (CH)" physical value stored in the message */ inline const wreport::Var* get_cloud_ch() const { return find(WR_VAR(0, 20, 12)); } /** Set the value of "Cloud type (CM)" from a variable of type int */ inline void set_cloud_cm(int val) { seti(WR_VAR(0, 20, 12), val); } /** Get the "Cloud type (CM)" physical value stored in the message */ inline const wreport::Var* get_cloud_cm() const { return find(WR_VAR(0, 20, 12)); } /** Set the value of "Cloud type (CL)" from a variable of type int */ inline void set_cloud_cl(int val) { seti(WR_VAR(0, 20, 12), val); } /** Get the "Cloud type (CL)" physical value stored in the message */ inline const wreport::Var* get_cloud_cl() const { return find(WR_VAR(0, 20, 12)); } /** Set the value of "Cloud amount (NH)" from a variable of type int */ inline void set_cloud_nh(int val) { seti(WR_VAR(0, 20, 11), val); } /** Get the "Cloud amount (NH)" physical value stored in the message */ inline const wreport::Var* get_cloud_nh() const { return find(WR_VAR(0, 20, 11)); } /** Set the value of "Height of base of cloud (HH)" from a variable of type double */ inline void set_cloud_hh(double val) { setd(WR_VAR(0, 20, 13), val); } /** Get the "Height of base of cloud (HH)" physical value stored in the message */ inline const wreport::Var* get_cloud_hh() const { return find(WR_VAR(0, 20, 13)); } /** Set the value of "Wind direction at 10 metres above ground" from a variable of type double */ inline void set_wind_dir(double val) { setd(WR_VAR(0, 11, 1), val); } /** Get the "Wind direction at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wind_dir() const { return find(WR_VAR(0, 11, 1)); } /** Set the value of "Wind speed at 10 metres above ground" from a variable of type double */ inline void set_wind_speed(double val) { setd(WR_VAR(0, 11, 2), val); } /** Get the "Wind speed at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wind_speed() const { return find(WR_VAR(0, 11, 2)); } /** Set the value of "Extreme counterclockwise wind direction of a variable wind at 10 metres above ground" from a variable of type double */ inline void set_ex_ccw_wind(double val) { setd(WR_VAR(0, 11, 16), val); } /** Get the "Extreme counterclockwise wind direction of a variable wind at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_ex_ccw_wind() const { return find(WR_VAR(0, 11, 16)); } /** Set the value of "Extreme clockwise wind direction of a variable wind at 10 metres above ground" from a variable of type double */ inline void set_ex_cw_wind(double val) { setd(WR_VAR(0, 11, 17), val); } /** Get the "Extreme clockwise wind direction of a variable wind at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_ex_cw_wind() const { return find(WR_VAR(0, 11, 17)); } /** Set the value of "Maximum wind gust speed at 10 metres above ground" from a variable of type double */ inline void set_wind_gust_max_speed(double val) { setd(WR_VAR(0, 11, 41), val); } /** Get the "Maximum wind gust speed at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wind_gust_max_speed() const { return find(WR_VAR(0, 11, 41)); } /** Set the value of "Maximum wind gust direction at 10 metres above ground" from a variable of type double */ inline void set_wind_gust_max_dir(double val) { setd(WR_VAR(0, 11, 43), val); } /** Get the "Maximum wind gust direction at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wind_gust_max_dir() const { return find(WR_VAR(0, 11, 43)); } /** Set the value of "Altimeter setting (QNH)" from a variable of type double */ inline void set_qnh(double val) { setd(WR_VAR(0, 10, 52), val); } /** Get the "Altimeter setting (QNH)" physical value stored in the message */ inline const wreport::Var* get_qnh() const { return find(WR_VAR(0, 10, 52)); } /** Set the value of "Temperature at 2 metres above ground" from a variable of type double */ inline void set_temp_2m(double val) { setd(WR_VAR(0, 12, 101), val); } /** Get the "Temperature at 2 metres above ground" physical value stored in the message */ inline const wreport::Var* get_temp_2m() const { return find(WR_VAR(0, 12, 101)); } /** Set the value of "Wet bulb temperature at 2 metres above ground" from a variable of type double */ inline void set_wet_temp_2m(double val) { setd(WR_VAR(0, 12, 102), val); } /** Get the "Wet bulb temperature at 2 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wet_temp_2m() const { return find(WR_VAR(0, 12, 102)); } /** Set the value of "Dew point at 2 metres above ground" from a variable of type double */ inline void set_dewpoint_2m(double val) { setd(WR_VAR(0, 12, 103), val); } /** Get the "Dew point at 2 metres above ground" physical value stored in the message */ inline const wreport::Var* get_dewpoint_2m() const { return find(WR_VAR(0, 12, 103)); } /** Set the value of "Humidity at 2 metres above ground" from a variable of type double */ inline void set_humidity(double val) { setd(WR_VAR(0, 13, 3), val); } /** Get the "Humidity at 2 metres above ground" physical value stored in the message */ inline const wreport::Var* get_humidity() const { return find(WR_VAR(0, 13, 3)); } /** Set the value of "Pressure reduced to mean sea level" from a variable of type double */ inline void set_press_msl(double val) { setd(WR_VAR(0, 10, 51), val); } /** Get the "Pressure reduced to mean sea level" physical value stored in the message */ inline const wreport::Var* get_press_msl() const { return find(WR_VAR(0, 10, 51)); } /** Set the value of "Direction of motion of moving observing platform" from a variable of type int */ inline void set_st_dir(int val) { seti(WR_VAR(0, 1, 12), val); } /** Get the "Direction of motion of moving observing platform" physical value stored in the message */ inline const wreport::Var* get_st_dir() const { return find(WR_VAR(0, 1, 12)); } /** Set the value of "Speed of motion of moving observing platform" from a variable of type int */ inline void set_st_speed(int val) { seti(WR_VAR(0, 1, 13), val); } /** Get the "Speed of motion of moving observing platform" physical value stored in the message */ inline const wreport::Var* get_st_speed() const { return find(WR_VAR(0, 1, 13)); } /** Set the value of "Type of measuring equipment used" from a variable of type int */ inline void set_meas_equip_type(int val) { seti(WR_VAR(0, 2, 3), val); } /** Get the "Type of measuring equipment used" physical value stored in the message */ inline const wreport::Var* get_meas_equip_type() const { return find(WR_VAR(0, 2, 3)); } /** Set the value of "Radiosonde type" from a variable of type int */ inline void set_sonde_type(int val) { seti(WR_VAR(0, 2, 11), val); } /** Get the "Radiosonde type" physical value stored in the message */ inline const wreport::Var* get_sonde_type() const { return find(WR_VAR(0, 2, 11)); } /** Set the value of "Radiosonde computational method" from a variable of type int */ inline void set_sonde_method(int val) { seti(WR_VAR(0, 2, 12), val); } /** Get the "Radiosonde computational method" physical value stored in the message */ inline const wreport::Var* get_sonde_method() const { return find(WR_VAR(0, 2, 12)); } /** Set the value of "Solar and infrared radiation correction" from a variable of type int */ inline void set_sonde_correction(int val) { seti(WR_VAR(0, 2, 13), val); } /** Get the "Solar and infrared radiation correction" physical value stored in the message */ inline const wreport::Var* get_sonde_correction() const { return find(WR_VAR(0, 2, 13)); } /** Set the value of "Tracking technique/status of system used" from a variable of type int */ inline void set_sonde_tracking(int val) { seti(WR_VAR(0, 2, 14), val); } /** Get the "Tracking technique/status of system used" physical value stored in the message */ inline const wreport::Var* get_sonde_tracking() const { return find(WR_VAR(0, 2, 14)); } /** Set the value of "Pressure at ground level" from a variable of type double */ inline void set_press(double val) { setd(WR_VAR(0, 10, 4), val); } /** Get the "Pressure at ground level" physical value stored in the message */ inline const wreport::Var* get_press() const { return find(WR_VAR(0, 10, 4)); } /** Set the value of "Anemometer height" from a variable of type double */ inline void set_height_anem(double val) { setd(WR_VAR(0, 10, 197), val); } /** Get the "Anemometer height" physical value stored in the message */ inline const wreport::Var* get_height_anem() const { return find(WR_VAR(0, 10, 197)); } /** Set the value of "Total show depth" from a variable of type double */ inline void set_tot_snow(double val) { setd(WR_VAR(0, 13, 13), val); } /** Get the "Total show depth" physical value stored in the message */ inline const wreport::Var* get_tot_snow() const { return find(WR_VAR(0, 13, 13)); } /** Set the value of "Visibility" from a variable of type double */ inline void set_visibility(double val) { setd(WR_VAR(0, 20, 1), val); } /** Get the "Visibility" physical value stored in the message */ inline const wreport::Var* get_visibility() const { return find(WR_VAR(0, 20, 1)); } /** Set the value of "Present weather" from a variable of type int */ inline void set_pres_wtr(int val) { seti(WR_VAR(0, 20, 3), val); } /** Get the "Present weather" physical value stored in the message */ inline const wreport::Var* get_pres_wtr() const { return find(WR_VAR(0, 20, 3)); } /** Set the value of "General weather indicator (TAF/METAR)" from a variable of type int */ inline void set_metar_wtr(int val) { seti(WR_VAR(0, 20, 9), val); } /** Get the "General weather indicator (TAF/METAR)" physical value stored in the message */ inline const wreport::Var* get_metar_wtr() const { return find(WR_VAR(0, 20, 9)); } /** Set the value of "State of ground (with or without snow)" from a variable of type double */ inline void set_state_ground(double val) { setd(WR_VAR(0, 20, 62), val); } /** Get the "State of ground (with or without snow)" physical value stored in the message */ inline const wreport::Var* get_state_ground() const { return find(WR_VAR(0, 20, 62)); } /** Set the value of "Sea/water surface temperature" from a variable of type double */ inline void set_water_temp(double val) { setd(WR_VAR(0, 22, 43), val); } /** Get the "Sea/water surface temperature" physical value stored in the message */ inline const wreport::Var* get_water_temp() const { return find(WR_VAR(0, 22, 43)); } /** Set the value of "Past weather (1 - 6h)" from a variable of type int */ inline void set_past_wtr1_6h(int val) { seti(WR_VAR(0, 20, 4), val); } /** Get the "Past weather (1 - 6h)" physical value stored in the message */ inline const wreport::Var* get_past_wtr1_6h() const { return find(WR_VAR(0, 20, 4)); } /** Set the value of "Past weather (2 - 6h)" from a variable of type int */ inline void set_past_wtr2_6h(int val) { seti(WR_VAR(0, 20, 5), val); } /** Get the "Past weather (2 - 6h)" physical value stored in the message */ inline const wreport::Var* get_past_wtr2_6h() const { return find(WR_VAR(0, 20, 5)); } /** Set the value of "Characteristic of pressure tendency" from a variable of type double */ inline void set_press_tend(double val) { setd(WR_VAR(0, 10, 63), val); } /** Get the "Characteristic of pressure tendency" physical value stored in the message */ inline const wreport::Var* get_press_tend() const { return find(WR_VAR(0, 10, 63)); } /** Set the value of "Past weather (1 - 3h)" from a variable of type int */ inline void set_past_wtr1_3h(int val) { seti(WR_VAR(0, 20, 4), val); } /** Get the "Past weather (1 - 3h)" physical value stored in the message */ inline const wreport::Var* get_past_wtr1_3h() const { return find(WR_VAR(0, 20, 4)); } /** Set the value of "Past weather (2 - 3h)" from a variable of type int */ inline void set_past_wtr2_3h(int val) { seti(WR_VAR(0, 20, 5), val); } /** Get the "Past weather (2 - 3h)" physical value stored in the message */ inline const wreport::Var* get_past_wtr2_3h() const { return find(WR_VAR(0, 20, 5)); } /** Set the value of "24 hour pressure change at ground level" from a variable of type double */ inline void set_press_24h(double val) { setd(WR_VAR(0, 10, 60), val); } /** Get the "24 hour pressure change at ground level" physical value stored in the message */ inline const wreport::Var* get_press_24h() const { return find(WR_VAR(0, 10, 60)); } /** Set the value of "3 hour pressure change at ground level" from a variable of type double */ inline void set_press_3h(double val) { setd(WR_VAR(0, 10, 60), val); } /** Get the "3 hour pressure change at ground level" physical value stored in the message */ inline const wreport::Var* get_press_3h() const { return find(WR_VAR(0, 10, 60)); } /** Set the value of "Total precipitation in the last 24 hours" from a variable of type double */ inline void set_tot_prec24(double val) { setd(WR_VAR(0, 13, 11), val); } /** Get the "Total precipitation in the last 24 hours" physical value stored in the message */ inline const wreport::Var* get_tot_prec24() const { return find(WR_VAR(0, 13, 11)); } /** Set the value of "Total precipitation in the last 12 hours" from a variable of type double */ inline void set_tot_prec12(double val) { setd(WR_VAR(0, 13, 11), val); } /** Get the "Total precipitation in the last 12 hours" physical value stored in the message */ inline const wreport::Var* get_tot_prec12() const { return find(WR_VAR(0, 13, 11)); } /** Set the value of "Total precipitation in the last 6 hours" from a variable of type double */ inline void set_tot_prec6(double val) { setd(WR_VAR(0, 13, 11), val); } /** Get the "Total precipitation in the last 6 hours" physical value stored in the message */ inline const wreport::Var* get_tot_prec6() const { return find(WR_VAR(0, 13, 11)); } /** Set the value of "Total precipitation in the last 3 hours" from a variable of type double */ inline void set_tot_prec3(double val) { setd(WR_VAR(0, 13, 11), val); } /** Get the "Total precipitation in the last 3 hours" physical value stored in the message */ inline const wreport::Var* get_tot_prec3() const { return find(WR_VAR(0, 13, 11)); } /** Set the value of "Total precipitation in the last hour" from a variable of type double */ inline void set_tot_prec1(double val) { setd(WR_VAR(0, 13, 11), val); } /** Get the "Total precipitation in the last hour" physical value stored in the message */ inline const wreport::Var* get_tot_prec1() const { return find(WR_VAR(0, 13, 11)); } dballe-7.7/dballe/msg/filter.cc0000644000175000017500000000452712652630043013351 00000000000000/* * DB-ALLe - Archive for punctual meteorological data * * Copyright (C) 2005--2010 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "msg.h" #include "context.h" /* * 1: the message matches * 0: the message does not match */ static bool match_message(const Msg& m, const Record& filter) { #warning to be implemented return true; }; /* * 1: the context matches * 0: the context does not match */ static int match_context(dba_msg m, dba_msg_context l, dba_record filter) { #warning to be implemented return 1; }; /* * 1: the variable matches * 0: the variable does not match */ static int match_var(dba_msg m, dba_msg_context l, dba_var var, dba_record filter) { #warning to be implemented return 1; } dba_err dba_msg_filter_copy(dba_msg src, dba_msg* dst, dba_record filter) { dba_err err = DBA_OK; dba_msg res = NULL; int li, di; int copied = 0; if (!match_message(src, filter)) { *dst = NULL; return dba_error_ok(); } DBA_RUN_OR_RETURN(dba_msg_create(&res)); for (li = 0; li < src->data_count; ++li) { dba_msg_context l = src->data[li]; if (!match_context(src, l, filter)) continue; for (di = 0; di < l->data_count; ++di) { dba_var var = l->data[di]; if (!match_var(src, l, var, filter)) continue; DBA_RUN_OR_GOTO(cleanup, dba_msg_set(res, var, dba_var_code(var), l->ltype1, l->l1, l->ltype2, l->l2, l->pind, l->p1, l->p2)); ++copied; } } if (!copied) { dba_msg_delete(res); res = NULL; } // Hand over the new message to the caller *dst = res; res = NULL; cleanup: if (res) dba_msg_delete(res); return err == DBA_OK ? dba_error_ok() : err; } /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/msg/aof_codec.h0000644000175000017500000000655512652630043013633 00000000000000#ifndef DBALLE_AOF_CODEC_H #define DBALLE_AOF_CODEC_H /** @file * @ingroup aof * * AOF message codec. * * It provides various AOF encoding and decoding functions, and implements * dba_file reading and writing of AOF files. * * AOF records can be read, written and interpreted into a dba_msg. Encoding * from a dba_msg is not yet implemented. A "makeaof" tool exists, not part of * DB-All.e, that can convert BUFR messages into AOF. * * Endianness of the written records can be controlled by the environment * variable DBA_AOF_ENDIANNESS: * * \li \b ARCH writes using the host endianness * \li \n LE writes using little endian * \li \n BE writes using big endian * * If the environment variable is not set, the default is to write using the * host endianness. */ #include #include namespace dballe { struct Msg; namespace msg { class AOFImporter : public Importer { protected: // Message-specific code static void read_synop(const uint32_t* obs, int obs_len, Msg& msg); static void read_flight(const uint32_t* obs, int obs_len, Msg& msg); static void read_satob(const uint32_t* obs, int obs_len, Msg& msg); static void read_dribu(const uint32_t* obs, int obs_len, Msg& msg); static void read_temp(const uint32_t* obs, int obs_len, Msg& msg); static void read_pilot(const uint32_t* obs, int obs_len, Msg& msg); static void read_satem(const uint32_t* obs, int obs_len, Msg& msg); /// Parse WMO block and station numbers in the Observation Header static void parse_st_block_station(const uint32_t* obs, Msg& msg); /// Parse station altitude the Observation Header static void parse_altitude(const uint32_t* obs, Msg& msg); /// Parse string ident in the Observation Header static void parse_st_ident(const uint32_t* obs, Msg& msg); /** * Parse latitude, longitude, date and time in the Observation Header * * @returns the hour, which can be used to take decisions later */ static int parse_lat_lon_datetime(const uint32_t* obs, Msg& msg); /// Parse 27 Weather group in Synop observations static void parse_weather_group(const uint32_t* obs, Msg& msg, int hour); /// Parse 28 General cloud group in Synop observations static void parse_general_cloud_group(const uint32_t* obs, Msg& msg); /// Parse a bit-packed cloud group in Synop observations static void parse_cloud_group(uint32_t val, int* ns, int* c, int* h); public: AOFImporter(const Options& opts=Options()); virtual ~AOFImporter(); bool foreach_decoded(const BinaryMessage& msg, std::function&&)> dest) const override; Messages from_bulletin(const wreport::Bulletin& msg) const override; /** * Get category and subcategory of an AOF message * * @param msg * The message to scan * @retval category * The AOF category of the message * @retval subcategory * The AOF subcategory of the message */ static void get_category(const BinaryMessage& msg, int* category, int* subcategory); /** * Print the contents of the AOF message * * @param msg * The encoded message to dump * @param out * The stream to use to print the message */ static void dump(const BinaryMessage& msg, FILE* out); }; } // namespace msg } // namespace dballe /* vim:set ts=4 sw=4: */ #endif dballe-7.7/dballe/msg/bulletin-test.cc0000644000175000017500000001705512652630043014657 00000000000000#include "tests.h" #include "bulletin.h" #include #include #include #include #include using namespace std; using namespace wreport; using namespace dballe; using namespace dballe::tests; namespace { struct MemStream { FILE* out = nullptr; char* buf = nullptr; size_t len = 0; MemStream() : out(open_memstream(&buf, &len)) { if (!out) throw std::system_error(errno, std::system_category(), "cannot open an in-memory stream"); } ~MemStream() { if (out) fclose(out); if (buf) free(buf); } void close() { fclose(out); out = nullptr; } operator FILE*() { return out; } }; class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("csv", []() { auto bulletin = BufrBulletin::create(); bulletin->edition_number = 4; bulletin->originating_centre = 0; bulletin->originating_subcentre = 0; bulletin->data_category = 0; bulletin->data_subcategory = 1; bulletin->data_subcategory_local = 2; bulletin->master_table_version_number = 14; bulletin->master_table_version_number_local = 0; bulletin->rep_year = 2015; bulletin->rep_month = 4; bulletin->rep_day = 25; bulletin->rep_hour = 12; bulletin->rep_minute = 30; bulletin->rep_second = 45; bulletin->load_tables(); // An integer bulletin->datadesc.push_back(WR_VAR(0, 1, 1)); bulletin->obtain_subset(0).store_variable_i(WR_VAR(0, 1, 1), 14); // A string bulletin->datadesc.push_back(WR_VAR(0, 1, 6)); bulletin->obtain_subset(0).store_variable_c(WR_VAR(0, 1, 6), "EZ1234"); // A decimal bulletin->datadesc.push_back(WR_VAR(0, 1, 14)); bulletin->obtain_subset(0).store_variable_d(WR_VAR(0, 1, 14), 3.14); // An undefined variable bulletin->datadesc.push_back(WR_VAR(0, 1, 2)); bulletin->obtain_subset(0).store_variable_undef(WR_VAR(0, 1, 2)); MemStream out; // Write the message out msg::BulletinCSVWriter writer(out); writer.output_bulletin(*bulletin); fflush(out); // Read it back and check it vector lines; { str::Split split(string(out.buf, out.len), "\n"); std::copy(split.begin(), split.end(), std::back_inserter(lines)); } wassert(actual(lines.size()) == 21u); wassert(actual(lines[ 0]) == R"("Field","Value")"); wassert(actual(lines[ 1]) == R"("master_table_number",0)"); wassert(actual(lines[ 2]) == R"("data_category",0)"); wassert(actual(lines[ 3]) == R"("data_subcategory",1)"); wassert(actual(lines[ 4]) == R"("data_subcategory_local",2)"); wassert(actual(lines[ 5]) == R"("originating_centre",0)"); wassert(actual(lines[ 6]) == R"("originating_subcentre",0)"); wassert(actual(lines[ 7]) == R"("update_sequence_number",0)"); wassert(actual(lines[ 8]) == R"("representative_time","2015-04-25 12:30:45")"); wassert(actual(lines[ 9]) == R"("encoding","bufr")"); wassert(actual(lines[10]) == R"("edition_number",4)"); wassert(actual(lines[11]) == R"("master_table_version_number",14)"); wassert(actual(lines[12]) == R"("master_table_version_number_local",0)"); wassert(actual(lines[13]) == R"("compression","false")"); wassert(actual(lines[14]) == R"("optional_section",)"); wassert(actual(lines[15]) == R"("subset",1)"); wassert(actual(lines[16]) == R"("B01001",14)"); wassert(actual(lines[17]) == R"("B01006","EZ1234")"); wassert(actual(lines[18]) == R"("B01014",3.14)"); wassert(actual(lines[19]) == R"("B01002",)"); // Empty line because the last line ends with a newline and // str::Split sees it as a trailing empty token wassert(actual(lines[20]) == R"()"); // Write the bulletin out again, to see that titles are not repeated writer.output_bulletin(*bulletin); fflush(out); lines.clear(); { str::Split split(string(out.buf, out.len), "\n"); std::copy(split.begin(), split.end(), std::back_inserter(lines)); } wassert(actual(lines.size()) == 40u); wassert(actual(lines[ 0]) == R"("Field","Value")"); wassert(actual(lines[ 1]) == R"("master_table_number",0)"); wassert(actual(lines[ 2]) == R"("data_category",0)"); wassert(actual(lines[ 3]) == R"("data_subcategory",1)"); wassert(actual(lines[ 4]) == R"("data_subcategory_local",2)"); wassert(actual(lines[ 5]) == R"("originating_centre",0)"); wassert(actual(lines[ 6]) == R"("originating_subcentre",0)"); wassert(actual(lines[ 7]) == R"("update_sequence_number",0)"); wassert(actual(lines[ 8]) == R"("representative_time","2015-04-25 12:30:45")"); wassert(actual(lines[ 9]) == R"("encoding","bufr")"); wassert(actual(lines[10]) == R"("edition_number",4)"); wassert(actual(lines[11]) == R"("master_table_version_number",14)"); wassert(actual(lines[12]) == R"("master_table_version_number_local",0)"); wassert(actual(lines[13]) == R"("compression","false")"); wassert(actual(lines[14]) == R"("optional_section",)"); wassert(actual(lines[15]) == R"("subset",1)"); wassert(actual(lines[16]) == R"("B01001",14)"); wassert(actual(lines[17]) == R"("B01006","EZ1234")"); wassert(actual(lines[18]) == R"("B01014",3.14)"); wassert(actual(lines[19]) == R"("B01002",)"); wassert(actual(lines[20]) == R"("master_table_number",0)"); wassert(actual(lines[21]) == R"("data_category",0)"); wassert(actual(lines[22]) == R"("data_subcategory",1)"); wassert(actual(lines[23]) == R"("data_subcategory_local",2)"); wassert(actual(lines[24]) == R"("originating_centre",0)"); wassert(actual(lines[25]) == R"("originating_subcentre",0)"); wassert(actual(lines[26]) == R"("update_sequence_number",0)"); wassert(actual(lines[27]) == R"("representative_time","2015-04-25 12:30:45")"); wassert(actual(lines[28]) == R"("encoding","bufr")"); wassert(actual(lines[29]) == R"("edition_number",4)"); wassert(actual(lines[30]) == R"("master_table_version_number",14)"); wassert(actual(lines[31]) == R"("master_table_version_number_local",0)"); wassert(actual(lines[32]) == R"("compression","false")"); wassert(actual(lines[33]) == R"("optional_section",)"); wassert(actual(lines[34]) == R"("subset",1)"); wassert(actual(lines[35]) == R"("B01001",14)"); wassert(actual(lines[36]) == R"("B01006","EZ1234")"); wassert(actual(lines[37]) == R"("B01014",3.14)"); wassert(actual(lines[38]) == R"("B01002",)"); // Empty line because the last line ends with a newline and // str::Split sees it as a trailing empty token wassert(actual(lines[39]) == R"()"); }); } } test("msg_bulletin"); } dballe-7.7/dballe/msg/msg-extravars.h0000644000175000017500000017210412652630120014522 00000000000000/** Set the value of "WMO block number" from a variable of type int */ inline void set_block(int val, int conf=-1) { seti(WR_VAR(0, 1, 1), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "WMO block number" from a ::dba_var */ inline void set_block_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 1), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "WMO block number" physical value stored in the message */ inline const wreport::Var* get_block_var() const { return find_by_id(DBA_MSG_BLOCK); } /** Set the value of "WMO station number" from a variable of type int */ inline void set_station(int val, int conf=-1) { seti(WR_VAR(0, 1, 2), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "WMO station number" from a ::dba_var */ inline void set_station_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 2), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "WMO station number" physical value stored in the message */ inline const wreport::Var* get_station_var() const { return find_by_id(DBA_MSG_STATION); } /** Set the value of "Aircraft registration number or other identification" from a variable of type const char* */ inline void set_flight_reg_no(const char* val, int conf=-1) { setc(WR_VAR(0, 1, 8), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Aircraft registration number or other identification" from a ::dba_var */ inline void set_flight_reg_no_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 8), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Aircraft registration number or other identification" physical value stored in the message */ inline const wreport::Var* get_flight_reg_no_var() const { return find_by_id(DBA_MSG_FLIGHT_REG_NO); } /** Set the value of "Mobile station identifier" from a variable of type const char* */ inline void set_ident(const char* val, int conf=-1) { setc(WR_VAR(0, 1, 11), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Mobile station identifier" from a ::dba_var */ inline void set_ident_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 11), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Mobile station identifier" physical value stored in the message */ inline const wreport::Var* get_ident_var() const { return find_by_id(DBA_MSG_IDENT); } /** Set the value of "Station or site name" from a variable of type const char* */ inline void set_st_name(const char* val, int conf=-1) { setc(WR_VAR(0, 1, 19), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Station or site name" from a ::dba_var */ inline void set_st_name_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 19), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Station or site name" physical value stored in the message */ inline const wreport::Var* get_st_name_var() const { return find_by_id(DBA_MSG_ST_NAME); } /** Set the value of "ICAO location indicator" from a variable of type const char* */ inline void set_st_name_icao(const char* val, int conf=-1) { setc(WR_VAR(0, 1, 63), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "ICAO location indicator" from a ::dba_var */ inline void set_st_name_icao_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 63), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "ICAO location indicator" physical value stored in the message */ inline const wreport::Var* get_st_name_icao_var() const { return find_by_id(DBA_MSG_ST_NAME_ICAO); } /** Set the value of "Report mnemonic" from a variable of type const char* */ inline void set_rep_memo(const char* val, int conf=-1) { setc(WR_VAR(0, 1, 194), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Report mnemonic" from a ::dba_var */ inline void set_rep_memo_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 194), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Report mnemonic" physical value stored in the message */ inline const wreport::Var* get_rep_memo_var() const { return find_by_id(DBA_MSG_REP_MEMO); } /** Set the value of "Air quality observing station local code" from a variable of type int */ inline void set_poll_lcode(int val, int conf=-1) { seti(WR_VAR(0, 1, 212), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Air quality observing station local code" from a ::dba_var */ inline void set_poll_lcode_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 212), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Air quality observing station local code" physical value stored in the message */ inline const wreport::Var* get_poll_lcode_var() const { return find_by_id(DBA_MSG_POLL_LCODE); } /** Set the value of "Airbase air quality observing station code" from a variable of type int */ inline void set_poll_scode(int val, int conf=-1) { seti(WR_VAR(0, 1, 213), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Airbase air quality observing station code" from a ::dba_var */ inline void set_poll_scode_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 213), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Airbase air quality observing station code" physical value stored in the message */ inline const wreport::Var* get_poll_scode_var() const { return find_by_id(DBA_MSG_POLL_SCODE); } /** Set the value of "GEMS air quality observing station code" from a variable of type int */ inline void set_poll_gemscode(int val, int conf=-1) { seti(WR_VAR(0, 1, 214), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "GEMS air quality observing station code" from a ::dba_var */ inline void set_poll_gemscode_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 214), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "GEMS air quality observing station code" physical value stored in the message */ inline const wreport::Var* get_poll_gemscode_var() const { return find_by_id(DBA_MSG_POLL_GEMSCODE); } /** Set the value of "Air quality observing station dominant emission source" from a variable of type int */ inline void set_poll_source(int val, int conf=-1) { seti(WR_VAR(0, 1, 215), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Air quality observing station dominant emission source" from a ::dba_var */ inline void set_poll_source_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 215), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Air quality observing station dominant emission source" physical value stored in the message */ inline const wreport::Var* get_poll_source_var() const { return find_by_id(DBA_MSG_POLL_SOURCE); } /** Set the value of "Air quality observing station area type" from a variable of type int */ inline void set_poll_atype(int val, int conf=-1) { seti(WR_VAR(0, 1, 216), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Air quality observing station area type" from a ::dba_var */ inline void set_poll_atype_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 216), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Air quality observing station area type" physical value stored in the message */ inline const wreport::Var* get_poll_atype_var() const { return find_by_id(DBA_MSG_POLL_ATYPE); } /** Set the value of "Air quality observing station terrain type" from a variable of type int */ inline void set_poll_ttype(int val, int conf=-1) { seti(WR_VAR(0, 1, 217), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Air quality observing station terrain type" from a ::dba_var */ inline void set_poll_ttype_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 217), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Air quality observing station terrain type" physical value stored in the message */ inline const wreport::Var* get_poll_ttype_var() const { return find_by_id(DBA_MSG_POLL_TTYPE); } /** Set the value of "Type of station" from a variable of type int */ inline void set_st_type(int val, int conf=-1) { seti(WR_VAR(0, 2, 1), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Type of station" from a ::dba_var */ inline void set_st_type_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 1), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Type of station" physical value stored in the message */ inline const wreport::Var* get_st_type_var() const { return find_by_id(DBA_MSG_ST_TYPE); } /** Set the value of "Type of instrumentation for wind measurement" from a variable of type int */ inline void set_wind_inst(int val, int conf=-1) { seti(WR_VAR(0, 2, 2), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Type of instrumentation for wind measurement" from a ::dba_var */ inline void set_wind_inst_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 2), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Type of instrumentation for wind measurement" physical value stored in the message */ inline const wreport::Var* get_wind_inst_var() const { return find_by_id(DBA_MSG_WIND_INST); } /** Set the value of "Precision of temperature observation" from a variable of type double */ inline void set_temp_precision(double val, int conf=-1) { setd(WR_VAR(0, 2, 5), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Precision of temperature observation" from a ::dba_var */ inline void set_temp_precision_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 5), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Precision of temperature observation" physical value stored in the message */ inline const wreport::Var* get_temp_precision_var() const { return find_by_id(DBA_MSG_TEMP_PRECISION); } /** Set the value of "Aircraft navigational system" from a variable of type int */ inline void set_navsys(int val, int conf=-1) { seti(WR_VAR(0, 2, 61), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Aircraft navigational system" from a ::dba_var */ inline void set_navsys_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 61), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Aircraft navigational system" physical value stored in the message */ inline const wreport::Var* get_navsys_var() const { return find_by_id(DBA_MSG_NAVSYS); } /** Set the value of "Aircraft data relay system" from a variable of type int */ inline void set_data_relay(int val, int conf=-1) { seti(WR_VAR(0, 2, 62), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Aircraft data relay system" from a ::dba_var */ inline void set_data_relay_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 62), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Aircraft data relay system" physical value stored in the message */ inline const wreport::Var* get_data_relay_var() const { return find_by_id(DBA_MSG_DATA_RELAY); } /** Set the value of "Aircraft roll angle" from a variable of type double */ inline void set_flight_roll(double val, int conf=-1) { setd(WR_VAR(0, 2, 63), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Aircraft roll angle" from a ::dba_var */ inline void set_flight_roll_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 63), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Aircraft roll angle" physical value stored in the message */ inline const wreport::Var* get_flight_roll_var() const { return find_by_id(DBA_MSG_FLIGHT_ROLL); } /** Set the value of "Original specification of latitude/longitude" from a variable of type int */ inline void set_latlon_spec(int val, int conf=-1) { seti(WR_VAR(0, 2, 70), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Original specification of latitude/longitude" from a ::dba_var */ inline void set_latlon_spec_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 70), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Original specification of latitude/longitude" physical value stored in the message */ inline const wreport::Var* get_latlon_spec_var() const { return find_by_id(DBA_MSG_LATLON_SPEC); } /** Set the value of "Year of the observation" from a variable of type int */ inline void set_year(int val, int conf=-1) { seti(WR_VAR(0, 4, 1), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Year of the observation" from a ::dba_var */ inline void set_year_var(const wreport::Var& val) { set(val, WR_VAR(0, 4, 1), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Year of the observation" physical value stored in the message */ inline const wreport::Var* get_year_var() const { return find_by_id(DBA_MSG_YEAR); } /** Set the value of "Month of the observation" from a variable of type int */ inline void set_month(int val, int conf=-1) { seti(WR_VAR(0, 4, 2), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Month of the observation" from a ::dba_var */ inline void set_month_var(const wreport::Var& val) { set(val, WR_VAR(0, 4, 2), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Month of the observation" physical value stored in the message */ inline const wreport::Var* get_month_var() const { return find_by_id(DBA_MSG_MONTH); } /** Set the value of "Day of the observation" from a variable of type int */ inline void set_day(int val, int conf=-1) { seti(WR_VAR(0, 4, 3), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Day of the observation" from a ::dba_var */ inline void set_day_var(const wreport::Var& val) { set(val, WR_VAR(0, 4, 3), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Day of the observation" physical value stored in the message */ inline const wreport::Var* get_day_var() const { return find_by_id(DBA_MSG_DAY); } /** Set the value of "Hour of the observation" from a variable of type int */ inline void set_hour(int val, int conf=-1) { seti(WR_VAR(0, 4, 4), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Hour of the observation" from a ::dba_var */ inline void set_hour_var(const wreport::Var& val) { set(val, WR_VAR(0, 4, 4), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Hour of the observation" physical value stored in the message */ inline const wreport::Var* get_hour_var() const { return find_by_id(DBA_MSG_HOUR); } /** Set the value of "Minute of the observation" from a variable of type int */ inline void set_minute(int val, int conf=-1) { seti(WR_VAR(0, 4, 5), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Minute of the observation" from a ::dba_var */ inline void set_minute_var(const wreport::Var& val) { set(val, WR_VAR(0, 4, 5), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Minute of the observation" physical value stored in the message */ inline const wreport::Var* get_minute_var() const { return find_by_id(DBA_MSG_MINUTE); } /** Set the value of "Second of the observation" from a variable of type int */ inline void set_second(int val, int conf=-1) { seti(WR_VAR(0, 4, 6), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Second of the observation" from a ::dba_var */ inline void set_second_var(const wreport::Var& val) { set(val, WR_VAR(0, 4, 6), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Second of the observation" physical value stored in the message */ inline const wreport::Var* get_second_var() const { return find_by_id(DBA_MSG_SECOND); } /** Set the value of "Latitude of the station" from a variable of type double */ inline void set_latitude(double val, int conf=-1) { setd(WR_VAR(0, 5, 1), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Latitude of the station" from a ::dba_var */ inline void set_latitude_var(const wreport::Var& val) { set(val, WR_VAR(0, 5, 1), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Latitude of the station" physical value stored in the message */ inline const wreport::Var* get_latitude_var() const { return find_by_id(DBA_MSG_LATITUDE); } /** Set the value of "Longiture of the station" from a variable of type double */ inline void set_longitude(double val, int conf=-1) { setd(WR_VAR(0, 6, 1), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Longiture of the station" from a ::dba_var */ inline void set_longitude_var(const wreport::Var& val) { set(val, WR_VAR(0, 6, 1), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Longiture of the station" physical value stored in the message */ inline const wreport::Var* get_longitude_var() const { return find_by_id(DBA_MSG_LONGITUDE); } /** Set the value of "Isobaric surface" from a variable of type double */ inline void set_isobaric_surface(double val, int conf=-1) { setd(WR_VAR(0, 7, 4), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Isobaric surface" from a ::dba_var */ inline void set_isobaric_surface_var(const wreport::Var& val) { set(val, WR_VAR(0, 7, 4), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Isobaric surface" physical value stored in the message */ inline const wreport::Var* get_isobaric_surface_var() const { return find_by_id(DBA_MSG_ISOBARIC_SURFACE); } /** Set the value of "Height of release of sonde above msl" from a variable of type double */ inline void set_height_release(double val, int conf=-1) { setd(WR_VAR(0, 7, 7), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Height of release of sonde above msl" from a ::dba_var */ inline void set_height_release_var(const wreport::Var& val) { set(val, WR_VAR(0, 7, 7), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Height of release of sonde above msl" physical value stored in the message */ inline const wreport::Var* get_height_release_var() const { return find_by_id(DBA_MSG_HEIGHT_RELEASE); } /** Set the value of "Height of station" from a variable of type double */ inline void set_height_station(double val, int conf=-1) { setd(WR_VAR(0, 7, 30), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Height of station" from a ::dba_var */ inline void set_height_station_var(const wreport::Var& val) { set(val, WR_VAR(0, 7, 30), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Height of station" physical value stored in the message */ inline const wreport::Var* get_height_station_var() const { return find_by_id(DBA_MSG_HEIGHT_STATION); } /** Set the value of "Height of barometer above mean sea level" from a variable of type double */ inline void set_height_baro(double val, int conf=-1) { setd(WR_VAR(0, 7, 31), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Height of barometer above mean sea level" from a ::dba_var */ inline void set_height_baro_var(const wreport::Var& val) { set(val, WR_VAR(0, 7, 31), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Height of barometer above mean sea level" physical value stored in the message */ inline const wreport::Var* get_height_baro_var() const { return find_by_id(DBA_MSG_HEIGHT_BARO); } /** Set the value of "Phase of aircraft flight" from a variable of type int */ inline void set_flight_phase(int val, int conf=-1) { seti(WR_VAR(0, 8, 4), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Phase of aircraft flight" from a ::dba_var */ inline void set_flight_phase_var(const wreport::Var& val) { set(val, WR_VAR(0, 8, 4), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Phase of aircraft flight" physical value stored in the message */ inline const wreport::Var* get_flight_phase_var() const { return find_by_id(DBA_MSG_FLIGHT_PHASE); } /** Set the value of "Time significance" from a variable of type int */ inline void set_timesig(int val, int conf=-1) { seti(WR_VAR(0, 8, 21), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Time significance" from a ::dba_var */ inline void set_timesig_var(const wreport::Var& val) { set(val, WR_VAR(0, 8, 21), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Time significance" physical value stored in the message */ inline const wreport::Var* get_timesig_var() const { return find_by_id(DBA_MSG_TIMESIG); } /** Set the value of "Station elevation quality mark (for mobile stations)" from a variable of type int */ inline void set_station_height_quality(int val, int conf=-1) { seti(WR_VAR(0, 33, 24), val, conf, Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Set the value of "Station elevation quality mark (for mobile stations)" from a ::dba_var */ inline void set_station_height_quality_var(const wreport::Var& val) { set(val, WR_VAR(0, 33, 24), Level(MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT), Trange(MISSING_INT, MISSING_INT, MISSING_INT)); } /** Get the "Station elevation quality mark (for mobile stations)" physical value stored in the message */ inline const wreport::Var* get_station_height_quality_var() const { return find_by_id(DBA_MSG_STATION_HEIGHT_QUALITY); } /** Set the value of "Total cloud cover (N)" from a variable of type int */ inline void set_cloud_n(int val, int conf=-1) { seti(WR_VAR(0, 20, 10), val, conf, Level(256, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Total cloud cover (N)" from a ::dba_var */ inline void set_cloud_n_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 10), Level(256, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Total cloud cover (N)" physical value stored in the message */ inline const wreport::Var* get_cloud_n_var() const { return find_by_id(DBA_MSG_CLOUD_N); } /** Set the value of "Cloud amount (N4)" from a variable of type int */ inline void set_cloud_n4(int val, int conf=-1) { seti(WR_VAR(0, 20, 11), val, conf, Level(256, MISSING_INT, 259, 4), Trange(254, 0, 0)); } /** Set the value of "Cloud amount (N4)" from a ::dba_var */ inline void set_cloud_n4_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 11), Level(256, MISSING_INT, 259, 4), Trange(254, 0, 0)); } /** Get the "Cloud amount (N4)" physical value stored in the message */ inline const wreport::Var* get_cloud_n4_var() const { return find_by_id(DBA_MSG_CLOUD_N4); } /** Set the value of "Cloud amount (C4)" from a variable of type int */ inline void set_cloud_c4(int val, int conf=-1) { seti(WR_VAR(0, 20, 12), val, conf, Level(256, MISSING_INT, 259, 4), Trange(254, 0, 0)); } /** Set the value of "Cloud amount (C4)" from a ::dba_var */ inline void set_cloud_c4_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 12), Level(256, MISSING_INT, 259, 4), Trange(254, 0, 0)); } /** Get the "Cloud amount (C4)" physical value stored in the message */ inline const wreport::Var* get_cloud_c4_var() const { return find_by_id(DBA_MSG_CLOUD_C4); } /** Set the value of "Height of base of cloud (H4)" from a variable of type double */ inline void set_cloud_h4(double val, int conf=-1) { setd(WR_VAR(0, 20, 13), val, conf, Level(256, MISSING_INT, 259, 4), Trange(254, 0, 0)); } /** Set the value of "Height of base of cloud (H4)" from a ::dba_var */ inline void set_cloud_h4_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 13), Level(256, MISSING_INT, 259, 4), Trange(254, 0, 0)); } /** Get the "Height of base of cloud (H4)" physical value stored in the message */ inline const wreport::Var* get_cloud_h4_var() const { return find_by_id(DBA_MSG_CLOUD_H4); } /** Set the value of "Cloud amount (N3)" from a variable of type int */ inline void set_cloud_n3(int val, int conf=-1) { seti(WR_VAR(0, 20, 11), val, conf, Level(256, MISSING_INT, 259, 3), Trange(254, 0, 0)); } /** Set the value of "Cloud amount (N3)" from a ::dba_var */ inline void set_cloud_n3_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 11), Level(256, MISSING_INT, 259, 3), Trange(254, 0, 0)); } /** Get the "Cloud amount (N3)" physical value stored in the message */ inline const wreport::Var* get_cloud_n3_var() const { return find_by_id(DBA_MSG_CLOUD_N3); } /** Set the value of "Cloud amount (C3)" from a variable of type int */ inline void set_cloud_c3(int val, int conf=-1) { seti(WR_VAR(0, 20, 12), val, conf, Level(256, MISSING_INT, 259, 3), Trange(254, 0, 0)); } /** Set the value of "Cloud amount (C3)" from a ::dba_var */ inline void set_cloud_c3_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 12), Level(256, MISSING_INT, 259, 3), Trange(254, 0, 0)); } /** Get the "Cloud amount (C3)" physical value stored in the message */ inline const wreport::Var* get_cloud_c3_var() const { return find_by_id(DBA_MSG_CLOUD_C3); } /** Set the value of "Height of base of cloud (H3)" from a variable of type double */ inline void set_cloud_h3(double val, int conf=-1) { setd(WR_VAR(0, 20, 13), val, conf, Level(256, MISSING_INT, 259, 3), Trange(254, 0, 0)); } /** Set the value of "Height of base of cloud (H3)" from a ::dba_var */ inline void set_cloud_h3_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 13), Level(256, MISSING_INT, 259, 3), Trange(254, 0, 0)); } /** Get the "Height of base of cloud (H3)" physical value stored in the message */ inline const wreport::Var* get_cloud_h3_var() const { return find_by_id(DBA_MSG_CLOUD_H3); } /** Set the value of "Cloud amount (N2)" from a variable of type int */ inline void set_cloud_n2(int val, int conf=-1) { seti(WR_VAR(0, 20, 11), val, conf, Level(256, MISSING_INT, 259, 2), Trange(254, 0, 0)); } /** Set the value of "Cloud amount (N2)" from a ::dba_var */ inline void set_cloud_n2_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 11), Level(256, MISSING_INT, 259, 2), Trange(254, 0, 0)); } /** Get the "Cloud amount (N2)" physical value stored in the message */ inline const wreport::Var* get_cloud_n2_var() const { return find_by_id(DBA_MSG_CLOUD_N2); } /** Set the value of "Cloud amount (C2)" from a variable of type int */ inline void set_cloud_c2(int val, int conf=-1) { seti(WR_VAR(0, 20, 12), val, conf, Level(256, MISSING_INT, 259, 2), Trange(254, 0, 0)); } /** Set the value of "Cloud amount (C2)" from a ::dba_var */ inline void set_cloud_c2_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 12), Level(256, MISSING_INT, 259, 2), Trange(254, 0, 0)); } /** Get the "Cloud amount (C2)" physical value stored in the message */ inline const wreport::Var* get_cloud_c2_var() const { return find_by_id(DBA_MSG_CLOUD_C2); } /** Set the value of "Height of base of cloud (H2)" from a variable of type double */ inline void set_cloud_h2(double val, int conf=-1) { setd(WR_VAR(0, 20, 13), val, conf, Level(256, MISSING_INT, 259, 2), Trange(254, 0, 0)); } /** Set the value of "Height of base of cloud (H2)" from a ::dba_var */ inline void set_cloud_h2_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 13), Level(256, MISSING_INT, 259, 2), Trange(254, 0, 0)); } /** Get the "Height of base of cloud (H2)" physical value stored in the message */ inline const wreport::Var* get_cloud_h2_var() const { return find_by_id(DBA_MSG_CLOUD_H2); } /** Set the value of "Cloud amount (N1)" from a variable of type int */ inline void set_cloud_n1(int val, int conf=-1) { seti(WR_VAR(0, 20, 11), val, conf, Level(256, MISSING_INT, 259, 1), Trange(254, 0, 0)); } /** Set the value of "Cloud amount (N1)" from a ::dba_var */ inline void set_cloud_n1_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 11), Level(256, MISSING_INT, 259, 1), Trange(254, 0, 0)); } /** Get the "Cloud amount (N1)" physical value stored in the message */ inline const wreport::Var* get_cloud_n1_var() const { return find_by_id(DBA_MSG_CLOUD_N1); } /** Set the value of "Cloud amount (C1)" from a variable of type int */ inline void set_cloud_c1(int val, int conf=-1) { seti(WR_VAR(0, 20, 12), val, conf, Level(256, MISSING_INT, 259, 1), Trange(254, 0, 0)); } /** Set the value of "Cloud amount (C1)" from a ::dba_var */ inline void set_cloud_c1_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 12), Level(256, MISSING_INT, 259, 1), Trange(254, 0, 0)); } /** Get the "Cloud amount (C1)" physical value stored in the message */ inline const wreport::Var* get_cloud_c1_var() const { return find_by_id(DBA_MSG_CLOUD_C1); } /** Set the value of "Height of base of cloud (H1)" from a variable of type double */ inline void set_cloud_h1(double val, int conf=-1) { setd(WR_VAR(0, 20, 13), val, conf, Level(256, MISSING_INT, 259, 1), Trange(254, 0, 0)); } /** Set the value of "Height of base of cloud (H1)" from a ::dba_var */ inline void set_cloud_h1_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 13), Level(256, MISSING_INT, 259, 1), Trange(254, 0, 0)); } /** Get the "Height of base of cloud (H1)" physical value stored in the message */ inline const wreport::Var* get_cloud_h1_var() const { return find_by_id(DBA_MSG_CLOUD_H1); } /** Set the value of "Cloud type (CH)" from a variable of type int */ inline void set_cloud_ch(int val, int conf=-1) { seti(WR_VAR(0, 20, 12), val, conf, Level(256, MISSING_INT, 258, 3), Trange(254, 0, 0)); } /** Set the value of "Cloud type (CH)" from a ::dba_var */ inline void set_cloud_ch_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 12), Level(256, MISSING_INT, 258, 3), Trange(254, 0, 0)); } /** Get the "Cloud type (CH)" physical value stored in the message */ inline const wreport::Var* get_cloud_ch_var() const { return find_by_id(DBA_MSG_CLOUD_CH); } /** Set the value of "Cloud type (CM)" from a variable of type int */ inline void set_cloud_cm(int val, int conf=-1) { seti(WR_VAR(0, 20, 12), val, conf, Level(256, MISSING_INT, 258, 2), Trange(254, 0, 0)); } /** Set the value of "Cloud type (CM)" from a ::dba_var */ inline void set_cloud_cm_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 12), Level(256, MISSING_INT, 258, 2), Trange(254, 0, 0)); } /** Get the "Cloud type (CM)" physical value stored in the message */ inline const wreport::Var* get_cloud_cm_var() const { return find_by_id(DBA_MSG_CLOUD_CM); } /** Set the value of "Cloud type (CL)" from a variable of type int */ inline void set_cloud_cl(int val, int conf=-1) { seti(WR_VAR(0, 20, 12), val, conf, Level(256, MISSING_INT, 258, 1), Trange(254, 0, 0)); } /** Set the value of "Cloud type (CL)" from a ::dba_var */ inline void set_cloud_cl_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 12), Level(256, MISSING_INT, 258, 1), Trange(254, 0, 0)); } /** Get the "Cloud type (CL)" physical value stored in the message */ inline const wreport::Var* get_cloud_cl_var() const { return find_by_id(DBA_MSG_CLOUD_CL); } /** Set the value of "Cloud amount (NH)" from a variable of type int */ inline void set_cloud_nh(int val, int conf=-1) { seti(WR_VAR(0, 20, 11), val, conf, Level(256, MISSING_INT, 258, 0), Trange(254, 0, 0)); } /** Set the value of "Cloud amount (NH)" from a ::dba_var */ inline void set_cloud_nh_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 11), Level(256, MISSING_INT, 258, 0), Trange(254, 0, 0)); } /** Get the "Cloud amount (NH)" physical value stored in the message */ inline const wreport::Var* get_cloud_nh_var() const { return find_by_id(DBA_MSG_CLOUD_NH); } /** Set the value of "Height of base of cloud (HH)" from a variable of type double */ inline void set_cloud_hh(double val, int conf=-1) { setd(WR_VAR(0, 20, 13), val, conf, Level(256, MISSING_INT, 258, 0), Trange(254, 0, 0)); } /** Set the value of "Height of base of cloud (HH)" from a ::dba_var */ inline void set_cloud_hh_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 13), Level(256, MISSING_INT, 258, 0), Trange(254, 0, 0)); } /** Get the "Height of base of cloud (HH)" physical value stored in the message */ inline const wreport::Var* get_cloud_hh_var() const { return find_by_id(DBA_MSG_CLOUD_HH); } /** Set the value of "Wind direction at 10 metres above ground" from a variable of type double */ inline void set_wind_dir(double val, int conf=-1) { setd(WR_VAR(0, 11, 1), val, conf, Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Wind direction at 10 metres above ground" from a ::dba_var */ inline void set_wind_dir_var(const wreport::Var& val) { set(val, WR_VAR(0, 11, 1), Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Wind direction at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wind_dir_var() const { return find_by_id(DBA_MSG_WIND_DIR); } /** Set the value of "Wind speed at 10 metres above ground" from a variable of type double */ inline void set_wind_speed(double val, int conf=-1) { setd(WR_VAR(0, 11, 2), val, conf, Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Wind speed at 10 metres above ground" from a ::dba_var */ inline void set_wind_speed_var(const wreport::Var& val) { set(val, WR_VAR(0, 11, 2), Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Wind speed at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wind_speed_var() const { return find_by_id(DBA_MSG_WIND_SPEED); } /** Set the value of "Extreme counterclockwise wind direction of a variable wind at 10 metres above ground" from a variable of type double */ inline void set_ex_ccw_wind(double val, int conf=-1) { setd(WR_VAR(0, 11, 16), val, conf, Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Extreme counterclockwise wind direction of a variable wind at 10 metres above ground" from a ::dba_var */ inline void set_ex_ccw_wind_var(const wreport::Var& val) { set(val, WR_VAR(0, 11, 16), Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Extreme counterclockwise wind direction of a variable wind at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_ex_ccw_wind_var() const { return find_by_id(DBA_MSG_EX_CCW_WIND); } /** Set the value of "Extreme clockwise wind direction of a variable wind at 10 metres above ground" from a variable of type double */ inline void set_ex_cw_wind(double val, int conf=-1) { setd(WR_VAR(0, 11, 17), val, conf, Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Extreme clockwise wind direction of a variable wind at 10 metres above ground" from a ::dba_var */ inline void set_ex_cw_wind_var(const wreport::Var& val) { set(val, WR_VAR(0, 11, 17), Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Extreme clockwise wind direction of a variable wind at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_ex_cw_wind_var() const { return find_by_id(DBA_MSG_EX_CW_WIND); } /** Set the value of "Maximum wind gust speed at 10 metres above ground" from a variable of type double */ inline void set_wind_gust_max_speed(double val, int conf=-1) { setd(WR_VAR(0, 11, 41), val, conf, Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Maximum wind gust speed at 10 metres above ground" from a ::dba_var */ inline void set_wind_gust_max_speed_var(const wreport::Var& val) { set(val, WR_VAR(0, 11, 41), Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Maximum wind gust speed at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wind_gust_max_speed_var() const { return find_by_id(DBA_MSG_WIND_GUST_MAX_SPEED); } /** Set the value of "Maximum wind gust direction at 10 metres above ground" from a variable of type double */ inline void set_wind_gust_max_dir(double val, int conf=-1) { setd(WR_VAR(0, 11, 43), val, conf, Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Maximum wind gust direction at 10 metres above ground" from a ::dba_var */ inline void set_wind_gust_max_dir_var(const wreport::Var& val) { set(val, WR_VAR(0, 11, 43), Level(103, 10000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Maximum wind gust direction at 10 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wind_gust_max_dir_var() const { return find_by_id(DBA_MSG_WIND_GUST_MAX_DIR); } /** Set the value of "Altimeter setting (QNH)" from a variable of type double */ inline void set_qnh(double val, int conf=-1) { setd(WR_VAR(0, 10, 52), val, conf, Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Altimeter setting (QNH)" from a ::dba_var */ inline void set_qnh_var(const wreport::Var& val) { set(val, WR_VAR(0, 10, 52), Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Altimeter setting (QNH)" physical value stored in the message */ inline const wreport::Var* get_qnh_var() const { return find_by_id(DBA_MSG_QNH); } /** Set the value of "Temperature at 2 metres above ground" from a variable of type double */ inline void set_temp_2m(double val, int conf=-1) { setd(WR_VAR(0, 12, 101), val, conf, Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Temperature at 2 metres above ground" from a ::dba_var */ inline void set_temp_2m_var(const wreport::Var& val) { set(val, WR_VAR(0, 12, 101), Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Temperature at 2 metres above ground" physical value stored in the message */ inline const wreport::Var* get_temp_2m_var() const { return find_by_id(DBA_MSG_TEMP_2M); } /** Set the value of "Wet bulb temperature at 2 metres above ground" from a variable of type double */ inline void set_wet_temp_2m(double val, int conf=-1) { setd(WR_VAR(0, 12, 102), val, conf, Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Wet bulb temperature at 2 metres above ground" from a ::dba_var */ inline void set_wet_temp_2m_var(const wreport::Var& val) { set(val, WR_VAR(0, 12, 102), Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Wet bulb temperature at 2 metres above ground" physical value stored in the message */ inline const wreport::Var* get_wet_temp_2m_var() const { return find_by_id(DBA_MSG_WET_TEMP_2M); } /** Set the value of "Dew point at 2 metres above ground" from a variable of type double */ inline void set_dewpoint_2m(double val, int conf=-1) { setd(WR_VAR(0, 12, 103), val, conf, Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Dew point at 2 metres above ground" from a ::dba_var */ inline void set_dewpoint_2m_var(const wreport::Var& val) { set(val, WR_VAR(0, 12, 103), Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Dew point at 2 metres above ground" physical value stored in the message */ inline const wreport::Var* get_dewpoint_2m_var() const { return find_by_id(DBA_MSG_DEWPOINT_2M); } /** Set the value of "Humidity at 2 metres above ground" from a variable of type double */ inline void set_humidity(double val, int conf=-1) { setd(WR_VAR(0, 13, 3), val, conf, Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Humidity at 2 metres above ground" from a ::dba_var */ inline void set_humidity_var(const wreport::Var& val) { set(val, WR_VAR(0, 13, 3), Level(103, 2000, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Humidity at 2 metres above ground" physical value stored in the message */ inline const wreport::Var* get_humidity_var() const { return find_by_id(DBA_MSG_HUMIDITY); } /** Set the value of "Pressure reduced to mean sea level" from a variable of type double */ inline void set_press_msl(double val, int conf=-1) { setd(WR_VAR(0, 10, 51), val, conf, Level(101, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Pressure reduced to mean sea level" from a ::dba_var */ inline void set_press_msl_var(const wreport::Var& val) { set(val, WR_VAR(0, 10, 51), Level(101, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Pressure reduced to mean sea level" physical value stored in the message */ inline const wreport::Var* get_press_msl_var() const { return find_by_id(DBA_MSG_PRESS_MSL); } /** Set the value of "Direction of motion of moving observing platform" from a variable of type int */ inline void set_st_dir(int val, int conf=-1) { seti(WR_VAR(0, 1, 12), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Direction of motion of moving observing platform" from a ::dba_var */ inline void set_st_dir_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 12), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Direction of motion of moving observing platform" physical value stored in the message */ inline const wreport::Var* get_st_dir_var() const { return find_by_id(DBA_MSG_ST_DIR); } /** Set the value of "Speed of motion of moving observing platform" from a variable of type int */ inline void set_st_speed(int val, int conf=-1) { seti(WR_VAR(0, 1, 13), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Speed of motion of moving observing platform" from a ::dba_var */ inline void set_st_speed_var(const wreport::Var& val) { set(val, WR_VAR(0, 1, 13), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Speed of motion of moving observing platform" physical value stored in the message */ inline const wreport::Var* get_st_speed_var() const { return find_by_id(DBA_MSG_ST_SPEED); } /** Set the value of "Type of measuring equipment used" from a variable of type int */ inline void set_meas_equip_type(int val, int conf=-1) { seti(WR_VAR(0, 2, 3), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Type of measuring equipment used" from a ::dba_var */ inline void set_meas_equip_type_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 3), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Type of measuring equipment used" physical value stored in the message */ inline const wreport::Var* get_meas_equip_type_var() const { return find_by_id(DBA_MSG_MEAS_EQUIP_TYPE); } /** Set the value of "Radiosonde type" from a variable of type int */ inline void set_sonde_type(int val, int conf=-1) { seti(WR_VAR(0, 2, 11), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Radiosonde type" from a ::dba_var */ inline void set_sonde_type_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 11), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Radiosonde type" physical value stored in the message */ inline const wreport::Var* get_sonde_type_var() const { return find_by_id(DBA_MSG_SONDE_TYPE); } /** Set the value of "Radiosonde computational method" from a variable of type int */ inline void set_sonde_method(int val, int conf=-1) { seti(WR_VAR(0, 2, 12), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Radiosonde computational method" from a ::dba_var */ inline void set_sonde_method_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 12), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Radiosonde computational method" physical value stored in the message */ inline const wreport::Var* get_sonde_method_var() const { return find_by_id(DBA_MSG_SONDE_METHOD); } /** Set the value of "Solar and infrared radiation correction" from a variable of type int */ inline void set_sonde_correction(int val, int conf=-1) { seti(WR_VAR(0, 2, 13), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Solar and infrared radiation correction" from a ::dba_var */ inline void set_sonde_correction_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 13), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Solar and infrared radiation correction" physical value stored in the message */ inline const wreport::Var* get_sonde_correction_var() const { return find_by_id(DBA_MSG_SONDE_CORRECTION); } /** Set the value of "Tracking technique/status of system used" from a variable of type int */ inline void set_sonde_tracking(int val, int conf=-1) { seti(WR_VAR(0, 2, 14), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Tracking technique/status of system used" from a ::dba_var */ inline void set_sonde_tracking_var(const wreport::Var& val) { set(val, WR_VAR(0, 2, 14), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Tracking technique/status of system used" physical value stored in the message */ inline const wreport::Var* get_sonde_tracking_var() const { return find_by_id(DBA_MSG_SONDE_TRACKING); } /** Set the value of "Pressure at ground level" from a variable of type double */ inline void set_press(double val, int conf=-1) { setd(WR_VAR(0, 10, 4), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Pressure at ground level" from a ::dba_var */ inline void set_press_var(const wreport::Var& val) { set(val, WR_VAR(0, 10, 4), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Pressure at ground level" physical value stored in the message */ inline const wreport::Var* get_press_var() const { return find_by_id(DBA_MSG_PRESS); } /** Set the value of "Anemometer height" from a variable of type double */ inline void set_height_anem(double val, int conf=-1) { setd(WR_VAR(0, 10, 197), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Anemometer height" from a ::dba_var */ inline void set_height_anem_var(const wreport::Var& val) { set(val, WR_VAR(0, 10, 197), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Anemometer height" physical value stored in the message */ inline const wreport::Var* get_height_anem_var() const { return find_by_id(DBA_MSG_HEIGHT_ANEM); } /** Set the value of "Total show depth" from a variable of type double */ inline void set_tot_snow(double val, int conf=-1) { setd(WR_VAR(0, 13, 13), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Total show depth" from a ::dba_var */ inline void set_tot_snow_var(const wreport::Var& val) { set(val, WR_VAR(0, 13, 13), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Total show depth" physical value stored in the message */ inline const wreport::Var* get_tot_snow_var() const { return find_by_id(DBA_MSG_TOT_SNOW); } /** Set the value of "Visibility" from a variable of type double */ inline void set_visibility(double val, int conf=-1) { setd(WR_VAR(0, 20, 1), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Visibility" from a ::dba_var */ inline void set_visibility_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 1), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Visibility" physical value stored in the message */ inline const wreport::Var* get_visibility_var() const { return find_by_id(DBA_MSG_VISIBILITY); } /** Set the value of "Present weather" from a variable of type int */ inline void set_pres_wtr(int val, int conf=-1) { seti(WR_VAR(0, 20, 3), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Present weather" from a ::dba_var */ inline void set_pres_wtr_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 3), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Present weather" physical value stored in the message */ inline const wreport::Var* get_pres_wtr_var() const { return find_by_id(DBA_MSG_PRES_WTR); } /** Set the value of "General weather indicator (TAF/METAR)" from a variable of type int */ inline void set_metar_wtr(int val, int conf=-1) { seti(WR_VAR(0, 20, 9), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "General weather indicator (TAF/METAR)" from a ::dba_var */ inline void set_metar_wtr_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 9), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "General weather indicator (TAF/METAR)" physical value stored in the message */ inline const wreport::Var* get_metar_wtr_var() const { return find_by_id(DBA_MSG_METAR_WTR); } /** Set the value of "State of ground (with or without snow)" from a variable of type double */ inline void set_state_ground(double val, int conf=-1) { setd(WR_VAR(0, 20, 62), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "State of ground (with or without snow)" from a ::dba_var */ inline void set_state_ground_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 62), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "State of ground (with or without snow)" physical value stored in the message */ inline const wreport::Var* get_state_ground_var() const { return find_by_id(DBA_MSG_STATE_GROUND); } /** Set the value of "Sea/water surface temperature" from a variable of type double */ inline void set_water_temp(double val, int conf=-1) { setd(WR_VAR(0, 22, 43), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Set the value of "Sea/water surface temperature" from a ::dba_var */ inline void set_water_temp_var(const wreport::Var& val) { set(val, WR_VAR(0, 22, 43), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(254, 0, 0)); } /** Get the "Sea/water surface temperature" physical value stored in the message */ inline const wreport::Var* get_water_temp_var() const { return find_by_id(DBA_MSG_WATER_TEMP); } /** Set the value of "Past weather (1 - 6h)" from a variable of type int */ inline void set_past_wtr1_6h(int val, int conf=-1) { seti(WR_VAR(0, 20, 4), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 21600)); } /** Set the value of "Past weather (1 - 6h)" from a ::dba_var */ inline void set_past_wtr1_6h_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 4), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 21600)); } /** Get the "Past weather (1 - 6h)" physical value stored in the message */ inline const wreport::Var* get_past_wtr1_6h_var() const { return find_by_id(DBA_MSG_PAST_WTR1_6H); } /** Set the value of "Past weather (2 - 6h)" from a variable of type int */ inline void set_past_wtr2_6h(int val, int conf=-1) { seti(WR_VAR(0, 20, 5), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 21600)); } /** Set the value of "Past weather (2 - 6h)" from a ::dba_var */ inline void set_past_wtr2_6h_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 5), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 21600)); } /** Get the "Past weather (2 - 6h)" physical value stored in the message */ inline const wreport::Var* get_past_wtr2_6h_var() const { return find_by_id(DBA_MSG_PAST_WTR2_6H); } /** Set the value of "Characteristic of pressure tendency" from a variable of type double */ inline void set_press_tend(double val, int conf=-1) { setd(WR_VAR(0, 10, 63), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 10800)); } /** Set the value of "Characteristic of pressure tendency" from a ::dba_var */ inline void set_press_tend_var(const wreport::Var& val) { set(val, WR_VAR(0, 10, 63), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 10800)); } /** Get the "Characteristic of pressure tendency" physical value stored in the message */ inline const wreport::Var* get_press_tend_var() const { return find_by_id(DBA_MSG_PRESS_TEND); } /** Set the value of "Past weather (1 - 3h)" from a variable of type int */ inline void set_past_wtr1_3h(int val, int conf=-1) { seti(WR_VAR(0, 20, 4), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 10800)); } /** Set the value of "Past weather (1 - 3h)" from a ::dba_var */ inline void set_past_wtr1_3h_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 4), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 10800)); } /** Get the "Past weather (1 - 3h)" physical value stored in the message */ inline const wreport::Var* get_past_wtr1_3h_var() const { return find_by_id(DBA_MSG_PAST_WTR1_3H); } /** Set the value of "Past weather (2 - 3h)" from a variable of type int */ inline void set_past_wtr2_3h(int val, int conf=-1) { seti(WR_VAR(0, 20, 5), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 10800)); } /** Set the value of "Past weather (2 - 3h)" from a ::dba_var */ inline void set_past_wtr2_3h_var(const wreport::Var& val) { set(val, WR_VAR(0, 20, 5), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(205, 0, 10800)); } /** Get the "Past weather (2 - 3h)" physical value stored in the message */ inline const wreport::Var* get_past_wtr2_3h_var() const { return find_by_id(DBA_MSG_PAST_WTR2_3H); } /** Set the value of "24 hour pressure change at ground level" from a variable of type double */ inline void set_press_24h(double val, int conf=-1) { setd(WR_VAR(0, 10, 60), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(4, 0, 86400)); } /** Set the value of "24 hour pressure change at ground level" from a ::dba_var */ inline void set_press_24h_var(const wreport::Var& val) { set(val, WR_VAR(0, 10, 60), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(4, 0, 86400)); } /** Get the "24 hour pressure change at ground level" physical value stored in the message */ inline const wreport::Var* get_press_24h_var() const { return find_by_id(DBA_MSG_PRESS_24H); } /** Set the value of "3 hour pressure change at ground level" from a variable of type double */ inline void set_press_3h(double val, int conf=-1) { setd(WR_VAR(0, 10, 60), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(4, 0, 10800)); } /** Set the value of "3 hour pressure change at ground level" from a ::dba_var */ inline void set_press_3h_var(const wreport::Var& val) { set(val, WR_VAR(0, 10, 60), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(4, 0, 10800)); } /** Get the "3 hour pressure change at ground level" physical value stored in the message */ inline const wreport::Var* get_press_3h_var() const { return find_by_id(DBA_MSG_PRESS_3H); } /** Set the value of "Total precipitation in the last 24 hours" from a variable of type double */ inline void set_tot_prec24(double val, int conf=-1) { setd(WR_VAR(0, 13, 11), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 86400)); } /** Set the value of "Total precipitation in the last 24 hours" from a ::dba_var */ inline void set_tot_prec24_var(const wreport::Var& val) { set(val, WR_VAR(0, 13, 11), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 86400)); } /** Get the "Total precipitation in the last 24 hours" physical value stored in the message */ inline const wreport::Var* get_tot_prec24_var() const { return find_by_id(DBA_MSG_TOT_PREC24); } /** Set the value of "Total precipitation in the last 12 hours" from a variable of type double */ inline void set_tot_prec12(double val, int conf=-1) { setd(WR_VAR(0, 13, 11), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 43200)); } /** Set the value of "Total precipitation in the last 12 hours" from a ::dba_var */ inline void set_tot_prec12_var(const wreport::Var& val) { set(val, WR_VAR(0, 13, 11), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 43200)); } /** Get the "Total precipitation in the last 12 hours" physical value stored in the message */ inline const wreport::Var* get_tot_prec12_var() const { return find_by_id(DBA_MSG_TOT_PREC12); } /** Set the value of "Total precipitation in the last 6 hours" from a variable of type double */ inline void set_tot_prec6(double val, int conf=-1) { setd(WR_VAR(0, 13, 11), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 21600)); } /** Set the value of "Total precipitation in the last 6 hours" from a ::dba_var */ inline void set_tot_prec6_var(const wreport::Var& val) { set(val, WR_VAR(0, 13, 11), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 21600)); } /** Get the "Total precipitation in the last 6 hours" physical value stored in the message */ inline const wreport::Var* get_tot_prec6_var() const { return find_by_id(DBA_MSG_TOT_PREC6); } /** Set the value of "Total precipitation in the last 3 hours" from a variable of type double */ inline void set_tot_prec3(double val, int conf=-1) { setd(WR_VAR(0, 13, 11), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 10800)); } /** Set the value of "Total precipitation in the last 3 hours" from a ::dba_var */ inline void set_tot_prec3_var(const wreport::Var& val) { set(val, WR_VAR(0, 13, 11), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 10800)); } /** Get the "Total precipitation in the last 3 hours" physical value stored in the message */ inline const wreport::Var* get_tot_prec3_var() const { return find_by_id(DBA_MSG_TOT_PREC3); } /** Set the value of "Total precipitation in the last hour" from a variable of type double */ inline void set_tot_prec1(double val, int conf=-1) { setd(WR_VAR(0, 13, 11), val, conf, Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 3600)); } /** Set the value of "Total precipitation in the last hour" from a ::dba_var */ inline void set_tot_prec1_var(const wreport::Var& val) { set(val, WR_VAR(0, 13, 11), Level(1, MISSING_INT, MISSING_INT, MISSING_INT), Trange(1, 0, 3600)); } /** Get the "Total precipitation in the last hour" physical value stored in the message */ inline const wreport::Var* get_tot_prec1_var() const { return find_by_id(DBA_MSG_TOT_PREC1); } dballe-7.7/dballe/msg/tests-lua.cc0000644000175000017500000001100512652630043013772 00000000000000/** * Copyright (C) 2008--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Author: Enrico Zini */ #include "tests-lua.h" #include #include using namespace std; namespace dballe { namespace tests { Lua::Lua(const std::string& src) : L(NULL) { // Initialise the lua logic L = luaL_newstate(); // NOTE: This one is optional: only use it for debugging #if LUA_VERSION_NUM >= 501 luaL_openlibs(L); #else luaopen_base(L); /* opens the basic library */ luaopen_table(L); /* opens the table library */ luaopen_io(L); /* opens the I/O library */ luaopen_string(L); /* opens the string lib. */ luaopen_math(L); /* opens the math lib. */ luaopen_loadlib(L); /* loadlib function */ luaopen_debug(L); /* debug library */ lua_settop(L, 0); #endif if (!src.empty()) loadString(src); } Lua::~Lua() { if (L) lua_close(L); } /// Load the test code from the given file void Lua::loadFile(const std::string& fname) { /// Load the prettyprinting functions m_filename = fname; if (luaL_loadfile(L, fname.c_str())) throw std::runtime_error(lua_tostring(L, -1)); create_lua_object(); } /// Load the test code from the given string containing Lua source code void Lua::loadString(const std::string& buf) { m_filename = "memory buffer"; if (luaL_loadbuffer(L, buf.data(), buf.size(), m_filename.c_str())) throw std::runtime_error(lua_tostring(L, -1)); create_lua_object(); } /// Runs the parsed code to let it define the 'test' function we are going /// to use void Lua::create_lua_object() { if (lua_pcall(L, 0, 0, 0)) { string error = lua_tostring(L, -1); lua_pop(L, 1); throw std::runtime_error(error); } // ensure that there is a 'test' function lua_getglobal(L, "test"); int type = lua_type(L, -1); if (type == LUA_TNIL) throw std::runtime_error("code did not define a function called 'test'"); if (type != LUA_TFUNCTION) throw std::runtime_error("the 'test' variable is not a function"); // Pop the 'test' function from the stack lua_pop(L, 1); } // From src/lbaselib.c in lua 5.1 /* ** If your system does not support `stdout', you can just remove this function. ** If you need, you can define your own `print' function, following this ** model but changing `fputs' to put the strings at a proper place ** (a console window or a log file, for instance). */ static int lua_ostream_print(lua_State *L) { // Access the closure parameters int outidx = lua_upvalueindex(1); void* ud = lua_touserdata(L, outidx); if (!ud) return luaL_error(L, "lua_report_print must be called as a closure with one userdata"); std::ostream& out = **(std::ostream**)ud; int n = lua_gettop(L); /* number of arguments */ int i; lua_getglobal(L, "tostring"); for (i=1; i<=n; i++) { const char *s; lua_pushvalue(L, -1); /* function to be called */ lua_pushvalue(L, i); /* value to print */ lua_call(L, 1, 1); s = lua_tostring(L, -1); /* get result */ if (s == NULL) return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("print")); if (i>1) out << '\t'; out << s; lua_pop(L, 1); /* pop result */ } out << endl; return 0; } void Lua::captureOutput(std::ostream& buf) { // Create a C closure with the print function and the ostream to use std::ostream** s = (std::ostream**)lua_newuserdata(L, sizeof(std::ostream*)); *s = &buf; lua_pushcclosure(L, lua_ostream_print, 1); // redefine print lua_setglobal(L, "print"); } std::string Lua::run() { // Call the function without arguments lua_getglobal(L, "test"); if (lua_pcall(L, 0, 1, 0)) { string error = lua_tostring(L, -1); lua_pop(L, 1); throw std::runtime_error(error); } const char* res = lua_tostring(L, -1); lua_pop(L, 1); return res == NULL ? string() : res; } } } // vim:set ts=4 sw=4: dballe-7.7/dballe/msg/mkvars0000755000175000017500000001602112652630043012776 00000000000000#!/usr/bin/python # # DB-ALLe - Archive for punctual meteorological data # # Copyright (C) 2005--2010 ARPA-SIM # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # Author: Enrico Zini import sys, re, os DESTDIR = "." if len(sys.argv) > 1: DESTDIR = sys.argv[1] class VC: def __init__(self, name): m = re.match(r"B(\d\d)(\d\d\d)", name) if not m: raise "Invalid B local" self.x = int(m.group(1)) self.y = int(m.group(2)) def __str__(self): return "B%02d%03d" % (self.x, self.y) def __cmp__(self, o): c = self.x.__cmp__(o.x) if c != 0: return c return self.y.__cmp__(o.y) class Var: def __init__(self, line): def cleanint(x): if x == '-': return "MISSING_INT" return str(int(x)) vals = re.split(r"\s*,\s*", line[:-1].strip()) self.name, self.type = vals[0:2] self.b = VC(vals[2]) self.letr = [cleanint(x) for x in vals[3:-1]] self.desc = vals[-1] def __str__(self): return ", ".join([self.name, str(self.b), ":".join([str(x) for x in self.letr[0:4]]), ":".join([str(x) for x in self.letr[4:]]), self.desc]) def __cmp__(self, o): def cmpval(a, b): if a == "MISSING_INT" and b == "MISSING_INT": return 0 if a == "MISSING_INT": return -1; if b == "MISSING_INT": return 1; return int(b) - int(a) for i in range(len(self.letr)): c = cmpval(self.letr[i], o.letr[i]) if c != 0: return c return self.b.__cmp__(o.b) vars = [Var(line) for line in sys.stdin if not re.match(r"^\s*(?:#.+)?$", line)] vars.sort() fh = open("%s/vars.h" % DESTDIR, "w") print >>fh, """#ifndef DBA_MSG_VARS_H #define DBA_MSG_VARS_H /** @file * @ingroup msg * Shortcut IDs and functions to quickly refer to commonly used values inside a * ::dba_msg. * * The shortcuts are defined in the file vars.csv, which maps a name to the tuple * (preferred C type, BLocal, Level type, L1, L2, P indicator, P1, P2). The file * vars.csv is used to generate code (vars.h and vars.c) that provides a set of * getters and setters for every named value. */ #include namespace dballe { /** * Full data corresponding to a shortcut ID */ struct MsgVarShortcut { /** Variable description code */ wreport::Varcode code; /** Type of the first level. See @ref level_table. */ int ltype1; /** L1 value of the level. See @ref level_table. */ int l1; /** Type of the second level. See @ref level_table. */ int ltype2; /** L2 value of the level. See @ref level_table. */ int l2; /** Time range type indicator. See @ref trange_table. */ int pind; /** Time range P1 indicator. See @ref trange_table. */ int p1; /** Time range P2 indicator. See @ref trange_table. */ int p2; }; /** Array with all the full expansions of the shortcut IDs, indexed by shortcut * ID */ extern struct MsgVarShortcut shortcutTable[]; /** Resolve a var name to a var ID */ int resolve_var(const char* name); /** Resolve a var name to a var ID, avoiding to compute the length of name */ int resolve_var_substring(const char* name, int len); """ for i, v in enumerate(vars): print >>fh, "/** %s */" % v.desc print >>fh, "#define DBA_MSG_%s %d" % (v.name, i) print >>fh, "/** Number of items in dba_msg_vartable */"; print >>fh, "#define DBA_MSG_VARTABLE_SIZE %d" % i; print >>fh, """ } #endif """ fh.close() fh = open("%s/msg-extravars.h" % DESTDIR, "w") types = dict(int = 'int', num = 'double', str = 'const char*') ftypes = dict(int = 'i', num = 'd', str = 'c') for v in vars: print >>fh, "/** Set the value of \"%s\" from a variable of type %s */" % (v.desc, types[v.type]) print >>fh, "inline void set_%s(%s val, int conf=-1) " % (v.name.lower(), types[v.type]), #print >>sys.stderr, v #print >>sys.stderr, "--", [ftypes[v.type], v.b.x, v.b.y] + v.letr; print >>fh, "{ set%s(WR_VAR(0, %d, %d), val, conf, Level(%s, %s, %s, %s), Trange(%s, %s, %s)); }" % \ tuple([ftypes[v.type], v.b.x, v.b.y] + v.letr); print >>fh, "/** Set the value of \"%s\" from a ::dba_var */" % v.desc; print >>fh, "inline void set_%s_var(const wreport::Var& val) " % v.name.lower(), print >>fh, "{ set(val, WR_VAR(0, %d, %d), Level(%s, %s, %s, %s), Trange(%s, %s, %s)); }" % \ tuple([v.b.x, v.b.y] + v.letr) print >>fh, "/** Get the \"%s\" physical value stored in the message */" % v.desc; print >>fh, "inline const wreport::Var* get_%s_var() const" % v.name.lower(); print >>fh, "{ return find_by_id(DBA_MSG_%s); }" % \ v.name; fh.close() fh = open("%s/context-extravars.h" % DESTDIR, "w") for v in vars: print >>fh, "/** Set the value of \"%s\" from a variable of type %s */" % (v.desc, types[v.type]) print >>fh, "inline void set_%s(%s val) " % (v.name.lower(), types[v.type]), print >>fh, "{ set%s(WR_VAR(0, %d, %d), val); }" % (ftypes[v.type], v.b.x, v.b.y) print >>fh, "/** Get the \"%s\" physical value stored in the message */" % v.desc; print >>fh, "inline const wreport::Var* get_%s() const" % v.name.lower(); print >>fh, "{ return find(WR_VAR(0, %d, %d)); }" % (v.b.x, v.b.y) fh.close() fc = open("%s/vars.gperf" % DESTDIR, "w") print >>fc, """ %define slot-name name %define class-name MsgVarLookup %define lookup-function-name find %struct-type %language=C++ %global-table %compare-strncmp /* Using %switch may be faster (remember to check when doing optimizations) */ %{ #include #include #include namespace dballe { %} struct msgvardef { const char* name; int var; }; %%""" for v in vars: print >>fc, "%s, DBA_MSG_%s" % (v.name.lower(), v.name) print >>fc, """%% int resolve_var(const char* name) { struct msgvardef* res = MsgVarLookup::find(name, strlen(name)); if (res == NULL) return -1; else return res->var; } int resolve_var_substring(const char* name, int len) { struct msgvardef* res = MsgVarLookup::find(name, len); if (res == NULL) return -1; else return res->var; } """ print >>fc, "struct MsgVarShortcut shortcutTable[] = {" for v in vars: print >>fc, " { WR_VAR(0, %d, %d), %s, %s, %s, %s, %s, %s, %s }," % tuple([v.b.x, v.b.y] + v.letr) print >>fc, "};" print >>fc, "} // namespace dballe" fc.close() sys.exit() dballe-7.7/dballe/msg/tests.h0000644000175000017500000002145012652630043013062 00000000000000#include #include #include #include namespace wreport { struct Vartable; } namespace dballe { namespace tests { Messages read_msgs(const char* filename, File::Encoding type, const dballe::msg::Importer::Options& opts=dballe::msg::Importer::Options()); Messages read_msgs_csv(const char* filename); struct ActualMessage : public Actual { using Actual::Actual; void is_undef(int shortcut) const; }; inline ActualMessage actual(const Message& message) { return ActualMessage(message); } std::unique_ptr export_msgs(File::Encoding enctype, const Messages& in, const std::string& tag, const dballe::msg::Exporter::Options& opts=dballe::msg::Exporter::Options()); #define test_export_msgs(...) wcallchecked(export_msgs(__VA_ARGS__)) void track_different_msgs(const Message& msg1, const Message& msg2, const std::string& prefix); void track_different_msgs(const Messages& msgs1, const Messages& msgs2, const std::string& prefix); extern const char* bufr_files[]; extern const char* crex_files[]; extern const char* aof_files[]; const wreport::Var& want_var(const Message& msg, int shortcut); const wreport::Var& want_var(const Message& msg, wreport::Varcode code, const dballe::Level& lev, const dballe::Trange& tr); inline ActualVar actual(const Message& message, int shortcut) { return ActualVar(want_var(message, shortcut)); } inline ActualVar actual(const Message& message, wreport::Varcode code, const dballe::Level& lev, const dballe::Trange& tr) { return ActualVar(want_var(message, code, lev, tr)); } void dump(const std::string& tag, const Message& msg, const std::string& desc="message"); void dump(const std::string& tag, const Messages& msgs, const std::string& desc="message"); void dump(const std::string& tag, const wreport::Bulletin& bul, const std::string& desc="message"); void dump(const std::string& tag, const BinaryMessage& msg, const std::string& desc="message"); void dump(const std::string& tag, const std::string& str, const std::string& desc="message"); struct MessageTweaker { virtual ~MessageTweaker() {} virtual void tweak(Messages&) {} virtual std::string desc() const = 0; }; struct MessageTweakers { std::vector tweaks; ~MessageTweakers(); // Takes ownership of memory management void add(MessageTweaker* tweak); void apply(Messages& msgs); }; namespace tweaks { // Strip attributes from all variables in a Messages struct StripAttrs : public MessageTweaker { std::vector codes; void tweak(Messages& msgs); virtual std::string desc() const { return "StripAttrs"; } }; // Strip attributes from all variables in a Messages struct StripQCAttrs : public StripAttrs { StripQCAttrs(); virtual std::string desc() const { return "StripQCAttrs"; } }; // Strip attributes with substituted values struct StripSubstituteAttrs : public MessageTweaker { void tweak(Messages& msgs); virtual std::string desc() const { return "StripSubstituteAttrs"; } }; // Strip context attributes from all variables in a Messages struct StripContextAttrs : public StripAttrs { StripContextAttrs(); virtual std::string desc() const { return "StripContextAttrs"; } }; // Strip a user-defined list of vars from all levels struct StripVars : public MessageTweaker { std::vector codes; StripVars() {} StripVars(std::initializer_list codes) : codes(codes) {} void tweak(Messages& msgs); virtual std::string desc() const { return "StripVars"; } }; // Strip datetime variables in the station context struct StripDatetimeVars : public StripVars { StripDatetimeVars(); virtual std::string desc() const { return "StripDatetimeVars"; } }; // Round variables to account for a passage through legacy vars struct RoundLegacyVars : public MessageTweaker { const wreport::Vartable* table; RoundLegacyVars(); void tweak(Messages& msgs); virtual std::string desc() const { return "RoundLegacyVars"; } }; // Remove synop vars present in WMO templates but not in ECMWF templates struct RemoveSynopWMOOnlyVars : public MessageTweaker { void tweak(Messages& msgs); virtual std::string desc() const { return "RemoveSynopWMOOnlyVars"; } }; // Remove temp vars present in WMO templates but not in ECMWF templates struct RemoveTempWMOOnlyVars : public MessageTweaker { void tweak(Messages& msgs); virtual std::string desc() const { return "RemoveTempWMOOnlyVars"; } }; // Remove temp vars present only in an odd temp template for which we have // messages in the test suite struct RemoveOddTempTemplateOnlyVars : public StripVars { RemoveOddTempTemplateOnlyVars(); virtual std::string desc() const { return "RemoveOddTempTemplateOnlyVars"; } }; // Remove ground level with missing length of statistical processing, that // cannot be encoded in ECMWF templates struct RemoveSynopWMOOddprec : public MessageTweaker { void tweak(Messages& msgs); virtual std::string desc() const { return "RemoveSynopWMOOddprec"; } }; // Truncate station name to its canonical length struct TruncStName : public MessageTweaker { void tweak(Messages& msgs); virtual std::string desc() const { return "TruncStName"; } }; // Round geopotential with a B10003->B10008->B10009->B10008->B10003 round trip struct RoundGeopotential : public MessageTweaker { const wreport::Vartable* table; RoundGeopotential(); void tweak(Messages& msgs); virtual std::string desc() const { return "RoundGeopotential"; } }; // Add B10008 GEOPOTENTIAL to all height levels, with its value taken from the height struct HeightToGeopotential : public MessageTweaker { const wreport::Vartable* table; HeightToGeopotential(); void tweak(Messages& msgs); virtual std::string desc() const { return "HeightToGeopotential"; } }; // Round vertical sounding significance with a B08042->B08001->B08042 round trip struct RoundVSS : public MessageTweaker { void tweak(Messages& msgs); virtual std::string desc() const { return "RoundVSS"; } }; // Remove a context given its level and time range struct RemoveContext : public MessageTweaker { Level lev; Trange tr; RemoveContext(const Level& lev, const Trange& tr); void tweak(Messages& msgs); virtual std::string desc() const { return "RemoveContext"; } }; } struct TestMessage { std::string name; File::Encoding type; BinaryMessage raw; wreport::Bulletin* bulletin = 0; Messages msgs; TestMessage(File::Encoding type, const std::string& name); ~TestMessage(); void read_from_file(const std::string& fname, const msg::Importer::Options& input_opts); void read_from_raw(const BinaryMessage& msg, const msg::Importer::Options& input_opts); void read_from_msgs(const Messages& msgs, const msg::Exporter::Options& export_opts); void dump() const; }; struct TestCodec { std::string fname; File::Encoding type; bool verbose = false; msg::Importer::Options input_opts; msg::Exporter::Options output_opts; std::string expected_template; int expected_subsets = 1; int expected_min_vars = 1; int expected_data_category = MISSING_INT; int expected_data_subcategory = MISSING_INT; int expected_data_subcategory_local = MISSING_INT; MessageTweakers after_reimport_import; MessageTweakers after_reimport_reimport; MessageTweakers after_convert_import; MessageTweakers after_convert_reimport; void do_compare(const TestMessage& msg1, const TestMessage& msg2); TestCodec(const std::string& fname, File::Encoding type=File::BUFR); void configure_ecmwf_to_wmo_tweaks(); // "import, export, import again, compare" test void run_reimport(); // "import, export as different template, import again, compare" test void run_convert(const std::string& tplname); }; #if 0 /* Random message generation functions */ class msg_generator : public generator { public: dba_err fill_message(dba_msg msg, bool mobile); }; /* Message reading functions */ class msg_vector : public dba_raw_consumer, public std::vector { public: virtual ~msg_vector() { for (iterator i = begin(); i != end(); i++) dba_msgs_delete(*i); } virtual dba_err consume(dba_rawmsg raw) { dba_msgs msgs; DBA_RUN_OR_RETURN(dba_marshal_decode(raw, &msgs)); push_back(msgs); return dba_error_ok(); } }; template void my_ensure_msg_equals(const char* file, int line, dba_msg msg, int id, const char* idname, const T& value) { dba_var var = my_want_var(file, line, msg, id, idname); inner_ensure_var_equals(var, value); } #define gen_ensure_msg_equals(msg, id, value) my_ensure_msg_equals(__FILE__, __LINE__, (msg), (id), #id, (value)) #define inner_ensure_msg_equals(msg, id, value) my_ensure_msg_equals(file, line, (msg), (id), #id, (value)) #endif } } // vim:set ts=4 sw=4: dballe-7.7/dballe/msg/msg.cc0000644000175000017500000007133212652630043012650 00000000000000/* * dballe/msg - Hold an interpreted weather bulletin * * Copyright (C) 2005--2014 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "msg.h" #include "context.h" #include "dballe/msg/vars.h" #include "dballe/core/var.h" #include "dballe/core/csv.h" #include #include #include #include #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace msg { Messages messages_from_csv(CSVReader& in) { Messages res; string old_rep; bool first = true; while (true) { // Seek to beginning, skipping empty lines if (!in.move_to_data()) return res; if (in.cols.size() != 13) error_consistency::throwf("cannot parse CSV line has %zd fields instead of 13", in.cols.size()); if (first) { // If we are the first run, initialse old_* markers with the contents of this line old_rep = in.cols[2]; first = false; } else if (old_rep != in.cols[2]) // If Report changes, we are done break; unique_ptr msg(new Msg); bool has_next = msg->from_csv(in); res.append(std::move(msg)); if (!has_next) break; } return res; } void messages_to_csv(const Messages& msgs, std::ostream& out) { for (const auto& i: msgs) Msg::downcast(i).to_csv(out); } } const char* msg_type_name(MsgType type) { switch (type) { case MSG_GENERIC: return "generic"; case MSG_SYNOP: return "synop"; case MSG_PILOT: return "pilot"; case MSG_TEMP: return "temp"; case MSG_TEMP_SHIP: return "temp_ship"; case MSG_AIREP: return "airep"; case MSG_AMDAR: return "amdar"; case MSG_ACARS: return "acars"; case MSG_SHIP: return "ship"; case MSG_BUOY: return "buoy"; case MSG_METAR: return "metar"; case MSG_SAT: return "sat"; case MSG_POLLUTION: return "pollution"; } return "(unknown)"; } Msg::Msg() { type = MSG_GENERIC; } Msg::~Msg() { for (vector::iterator i = data.begin(); i != data.end(); ++i) delete *i; } Msg::Msg(const Msg& m) : m_datetime(m.m_datetime), type(m.type) { // Reserve space for the new contexts data.reserve(m.data.size()); // Copy the contexts for (vector::const_iterator i = m.data.begin(); i != m.data.end(); ++i) data.push_back(new msg::Context(**i)); } Msg& Msg::operator=(const Msg& m) { // Manage a = a if (this == &m) return *this; m_datetime = m.m_datetime; type = m.type; // Delete existing vars for (vector::iterator i = data.begin(); i != data.end(); ++i) delete *i; data.clear(); // Reserve space for the new contexts data.reserve(m.data.size()); // Copy the contexts for (vector::const_iterator i = m.data.begin(); i != m.data.end(); ++i) data.push_back(new msg::Context(**i)); return *this; } const Msg& Msg::downcast(const Message& o) { const Msg* ptr = dynamic_cast(&o); if (!ptr) throw error_consistency("Message given is not a Msg"); return *ptr; } Msg& Msg::downcast(Message& o) { Msg* ptr = dynamic_cast(&o); if (!ptr) throw error_consistency("Message given is not a Msg"); return *ptr; } std::unique_ptr Msg::clone() const { return unique_ptr(new Msg(*this)); } void Msg::clear() { type = MSG_GENERIC; for (vector::iterator i = data.begin(); i != data.end(); ++i) delete *i; data.clear(); } int Msg::find_index(const Level& lev, const Trange& tr) const { /* Binary search */ int low = 0, high = data.size() - 1; while (low <= high) { int middle = low + (high - low)/2; //fprintf(stderr, "DMFC lo %d hi %d mid %d\n", low, high, middle); int cmp = -data[middle]->compare(lev, tr); if (cmp < 0) high = middle - 1; else if (cmp > 0) low = middle + 1; else return middle; } return -1; } const msg::Context* Msg::find_context(const Level& lev, const Trange& tr) const { int pos = find_index(lev, tr); if (pos == -1) return NULL; return data[pos]; } const msg::Context* Msg::find_station_context() const { return find_context(Level(), Trange()); } msg::Context* Msg::edit_context(const Level& lev, const Trange& tr) { int pos = find_index(lev, tr); if (pos == -1) return NULL; return data[pos]; } msg::Context& Msg::obtain_station_context() { return obtain_context(Level(), Trange()); } msg::Context& Msg::obtain_context(const Level& lev, const Trange& tr) { int pos = find_index(lev, tr); if (pos == -1) { unique_ptr c(new msg::Context(lev, tr)); msg::Context* res = c.get(); add_context(std::move(c)); return *res; } return *data[pos]; } void Msg::add_context(unique_ptr&& ctx) { // Enlarge the data data.resize(data.size() + 1); /* Insertionsort. Crude, but our datasets should be too small for an * RB-Tree to be worth */ int pos; for (pos = data.size() - 1; pos > 0; --pos) { int cmp = data[pos - 1]->compare(*ctx); if (cmp > 0) data[pos] = data[pos - 1]; else if (cmp == 0) { data.erase(data.begin() + pos); throw error_consistency("attempting to add a context that already exists in the message"); } else break; } data[pos] = ctx.release(); } bool Msg::remove_context(const Level& lev, const Trange& tr) { int pos = find_index(lev, tr); if (pos == -1) return false; delete data[pos]; data.erase(data.begin() + pos); return true; } const Var* Msg::get(Varcode code, const Level& lev, const Trange& tr) const { const msg::Context* ctx = find_context(lev, tr); if (ctx == NULL) return NULL; return ctx->find(code); } wreport::Var* Msg::edit(wreport::Varcode code, const Level& lev, const Trange& tr) { msg::Context* ctx = edit_context(lev, tr); if (ctx == NULL) return NULL; return ctx->edit(code); } bool Msg::remove(wreport::Varcode code, const Level& lev, const Trange& tr) { msg::Context* ctx = edit_context(lev, tr); if (!ctx) return false; if (!ctx->remove(code)) return false; if (ctx->data.empty()) remove_context(lev, tr); return true; } const Var* Msg::find_by_id(int id) const { const MsgVarShortcut& v = shortcutTable[id]; return get(v.code, Level(v.ltype1, v.l1, v.ltype2, v.l2), Trange(v.pind, v.p1, v.p2)); } const msg::Context* Msg::find_context_by_id(int id) const { const MsgVarShortcut& v = shortcutTable[id]; return find_context(Level(v.ltype1, v.l1, v.ltype2, v.l2), Trange(v.pind, v.p1, v.p2)); } Var* Msg::edit_by_id(int id) { const MsgVarShortcut& v = shortcutTable[id]; return edit(v.code, Level(v.ltype1, v.l1, v.ltype2, v.l2), Trange(v.pind, v.p1, v.p2)); } namespace { struct VarContext { const Msg& msg; // Extract datetime, lat, lon const Var* lat; const Var* lon; const Var* memo; const char* rep_memo; VarContext(const Msg& m) : msg(m) { // Extract datetime, lat, lon lat = m.get_latitude_var(); lon = m.get_longitude_var(); memo = m.get_rep_memo_var(); if (memo) rep_memo = memo->enqc(); else rep_memo = Msg::repmemo_from_type(m.type); } void print(ostream& out, msg::Context& c) { // Longitude if (lon) out << setprecision(5) << lon->enqd() << ","; else out << ","; // Latitude if (lat) out << setprecision(5) << lat->enqd() << ","; else out << ","; // Report type out << rep_memo << ","; if (c.level != Level()) { // Datetime msg.get_datetime().to_stream_iso8601(out, ' '); out << ','; // Level c.level.to_stream(out, ""); out << ","; // Time range c.trange.to_stream(out, ""); out << ","; } else out << ",,,,,,,,"; } }; } void Msg::to_csv(std::ostream& out) const { VarContext vc(*this); for (std::vector::const_iterator ci = data.begin(); ci != data.end(); ++ci) { msg::Context& c = **ci; for (std::vector::const_iterator vi = c.data.begin(); vi != c.data.end(); ++vi) { Var& v = **vi; vc.print(out, c); out << varcode_format(v.code()) << ","; // B code csv_output_quoted_string(out, v.format("")); out << endl; // Add attribute columns for (const Var* a = v.next_attr(); a != NULL; a = a->next_attr()) { vc.print(out, c); out << varcode_format(v.code()) << "." << varcode_format(a->code()) << ","; // B code csv_output_quoted_string(out, a->format("")); out << endl; } } } } void Msg::csv_header(std::ostream& out) { out << "Longitude,Latitude,Report,Date,Level1,L1,Level2,L2,Time range,P1,P2,Varcode,Value" << endl; } namespace { // Convert a string to an integer value, returning MISSING_INT if the string is // empty or "-" int str_to_int(const char* str) { if (str == NULL || str[0] == 0 || strcmp(str, "-") == 0) return MISSING_INT; else return strtol(str, NULL, 10); } int str_to_int(const std::string& str) { if (str.empty() || str == "-") return MISSING_INT; else return stoi(str); } } bool Msg::from_csv(CSVReader& in) { // Seek to beginning, skipping empty lines if (!in.move_to_data()) return false; string old_lat, old_lon, old_rep, old_date; bool first = true; while (true) { // If there are empty lines, use them as separators if (in.cols.empty()) break; if (in.cols.size() != 13) error_consistency::throwf("cannot parse CSV line has %zd fields instead of 13", in.cols.size()); if (first) { // If we are the first run, initialse old_* markers with the contents of this line old_lon = in.cols[0]; old_lat = in.cols[1]; old_rep = in.cols[2]; old_date = in.cols[3]; set_latitude(strtod(old_lat.c_str(), NULL)); set_longitude(strtod(old_lon.c_str(), NULL)); set_rep_memo(old_rep.c_str()); if (!old_date.empty()) set_datetime(Datetime::from_iso8601(old_date.c_str())); type = type_from_repmemo(old_rep.c_str()); first = false; } else if (old_lon != in.cols[0] || old_lat != in.cols[1] || old_rep != in.cols[2]) { // If Longitude, Latitude or Report change, we are done break; } else if (old_date != in.cols[3]) { // In case of Date differences, we need to deal with station // information for which the date is left empty if (old_date.empty()) { // previous lines were station information, next line is data old_date = in.cols[3]; set_datetime(Datetime::from_iso8601(old_date.c_str())); } else if (in.cols[3].empty()) // previous lines were data, next line is station information ; // Keep the old date else // The date has changed, we are done. break; } // 0 1 2 3 4 5 6 7 8 9 10 11 12 // out << "Longitude,Latitude,Report,Date,Level1,L1,Level2,L2,Time range,P1,P2,Varcode,Value" << endl; // Acquire the data Level lev(str_to_int(in.cols[4]), str_to_int(in.cols[5]), str_to_int(in.cols[6]), str_to_int(in.cols[7])); if (in.cols[3].empty()) // If we have station info, set level accordingly lev = Level(); Trange tr(str_to_int(in.cols[8]), str_to_int(in.cols[9]), str_to_int(in.cols[10])); // Parse variable code if (in.cols[11].size() == 13) { // Bxxyyy.Bxxyyy: attribute Varcode vcode = varcode_parse(in.cols[11].substr(0, 6).c_str()); // Find master variable wreport::Var* var = edit(vcode, lev, tr); if (var == NULL) error_consistency::throwf("cannot find corresponding variable for attribute %s", in.cols[11].c_str()); Varcode acode = varcode_parse(in.cols[11].substr(7).c_str()); auto attr = newvar(acode); attr->setf(in.cols[12].c_str()); var->seta(move(attr)); } else if (in.cols[11].size() == 6) { // Bxxyyy: variable Varcode vcode = varcode_parse(in.cols[11].c_str()); unique_ptr var = newvar(vcode); var->setf(in.cols[12].c_str()); set(std::move(var), lev, tr); } else error_consistency::throwf("cannot parse variable code %s", in.cols[11].c_str()); if (!in.next()) break; } return true; } void Msg::print(FILE* out) const { fprintf(out, "%s message ", msg_type_name(type)); if (data.empty()) { fprintf(stderr, "(empty)\n"); return; } fprintf(out, "with %zd contexts:\n", data.size()); switch (type) { case MSG_PILOT: case MSG_TEMP: case MSG_TEMP_SHIP: for (vector::const_iterator i = data.begin(); i != data.end(); ++i) { const Var* vsig = (*i)->find_vsig(); if (vsig != NULL) { int vs = vsig->enqi(); fprintf(out, "Sounding #%zd (level %d -", (i - data.begin()) + 1, vs); if (vs & BUFR08042::MISSING) fprintf(out, " missing"); if (vs & BUFR08042::H2PRESS) fprintf(out, " h2press"); if (vs & BUFR08042::RESERVED) fprintf(out, " reserved"); if (vs & BUFR08042::REGIONAL) fprintf(out, " regional"); if (vs & BUFR08042::TOPWIND) fprintf(out, " topwind"); if (vs & BUFR08042::ENDMISSW) fprintf(out, " endmissw"); if (vs & BUFR08042::BEGMISSW) fprintf(out, " begmissw"); if (vs & BUFR08042::ENDMISSH) fprintf(out, " endmissh"); if (vs & BUFR08042::BEGMISSH) fprintf(out, " begmissh"); if (vs & BUFR08042::ENDMISST) fprintf(out, " endmisst"); if (vs & BUFR08042::BEGMISST) fprintf(out, " begmisst"); if (vs & BUFR08042::SIGWIND) fprintf(out, " sigwind"); if (vs & BUFR08042::SIGHUM) fprintf(out, " sighum"); if (vs & BUFR08042::SIGTEMP) fprintf(out, " sigtemp"); if (vs & BUFR08042::MAXWIND) fprintf(out, " maxwind"); if (vs & BUFR08042::TROPO) fprintf(out, " tropo"); if (vs & BUFR08042::STD) fprintf(out, " std"); if (vs & BUFR08042::SURFACE) fprintf(out, " surface"); fprintf(out, ") "); } (*i)->print(out); } break; default: for (vector::const_iterator i = data.begin(); i != data.end(); ++i) (*i)->print(out); break; } } static void context_summary(const msg::Context& c, ostream& out) { out << "c(" << c.level << ", " << c.trange << ")"; } unsigned Msg::diff(const Message& o) const { const Msg& msg = downcast(o); unsigned diffs = 0; if (type != msg.type) { notes::logf("the messages have different type (first is %s (%d), second is %s (%d))\n", msg_type_name(type), type, msg_type_name(msg.type), msg.type); ++diffs; } size_t i1 = 0, i2 = 0; while (i1 < data.size() || i2 < msg.data.size()) { if (i1 == data.size()) { notes::log() << "Context "; context_summary(*msg.data[i2], notes::log()); notes::log() << " exists only in the second message" << endl; ++i2; ++diffs; } else if (i2 == msg.data.size()) { notes::log() << "Context "; context_summary(*data[i1], notes::log()); notes::log() << " exists only in the first message" << endl; ++i1; ++diffs; } else { int cmp = data[i1]->compare(*msg.data[i2]); if (cmp == 0) { diffs += data[i1]->diff(*msg.data[i2]); ++i1; ++i2; } else if (cmp < 0) { if (data[i1]->data.size() != 0) { notes::log() << "Context "; context_summary(*data[i1], notes::log()); notes::log() << " exists only in the first message" << endl; ++diffs; } ++i1; } else { if (msg.data[i2]->data.size() != 0) { notes::log() << "Context "; context_summary(*msg.data[i2], notes::log()); notes::log() << " exists only in the second message" << endl; ++diffs; } ++i2; } } } return diffs; } void Msg::set_by_id(const wreport::Var& var, int shortcut) { const MsgVarShortcut& v = shortcutTable[shortcut]; return set(var, v.code, Level(v.ltype1, v.l1, v.ltype2, v.l2), Trange(v.pind, v.p1, v.p2)); } void Msg::set(const Var& var, Varcode code, const Level& lev, const Trange& tr) { set(var_copy_without_unset_attrs(var, code), lev, tr); } void Msg::set(std::unique_ptr&& var, const Level& lev, const Trange& tr) { msg::Context& ctx = obtain_context(lev, tr); ctx.set(std::move(var)); } void Msg::seti(Varcode code, int val, int conf, const Level& lev, const Trange& tr) { unique_ptr var(newvar(code, val)); if (conf != -1) var->seta(newvar(WR_VAR(0, 33, 7), conf)); set(std::move(var), lev, tr); } void Msg::setd(Varcode code, double val, int conf, const Level& lev, const Trange& tr) { unique_ptr var(newvar(code, val)); if (conf != -1) var->seta(newvar(WR_VAR(0, 33, 7), conf)); set(std::move(var), lev, tr); } void Msg::setc(Varcode code, const char* val, int conf, const Level& lev, const Trange& tr) { unique_ptr var(newvar(code, val)); if (conf != -1) var->seta(newvar(WR_VAR(0, 33, 7), conf)); set(std::move(var), lev, tr); } MsgType Msg::type_from_repmemo(const char* repmemo) { if (repmemo == NULL || repmemo[0] == 0) return MSG_GENERIC; switch (tolower(repmemo[0])) { case 'a': if (strcasecmp(repmemo+1, "cars")==0) return MSG_ACARS; if (strcasecmp(repmemo+1, "irep")==0) return MSG_AIREP; if (strcasecmp(repmemo+1, "mdar")==0) return MSG_AMDAR; break; case 'b': if (strcasecmp(repmemo+1, "uoy")==0) return MSG_BUOY; break; case 'm': if (strcasecmp(repmemo+1, "etar")==0) return MSG_METAR; break; case 'p': if (strcasecmp(repmemo+1, "ilot")==0) return MSG_PILOT; if (strcasecmp(repmemo+1, "ollution")==0) return MSG_POLLUTION; break; case 's': if (strcasecmp(repmemo+1, "atellite")==0) return MSG_SAT; if (strcasecmp(repmemo+1, "hip")==0) return MSG_SHIP; if (strcasecmp(repmemo+1, "ynop")==0) return MSG_SYNOP; break; case 't': if (strcasecmp(repmemo+1, "emp")==0) return MSG_TEMP; if (strcasecmp(repmemo+1, "empship")==0) return MSG_TEMP_SHIP; break; } return MSG_GENERIC; } const char* Msg::repmemo_from_type(MsgType type) { switch (type) { case MSG_SYNOP: return "synop"; case MSG_METAR: return "metar"; case MSG_SHIP: return "ship"; case MSG_BUOY: return "buoy"; case MSG_AIREP: return "airep"; case MSG_AMDAR: return "amdar"; case MSG_ACARS: return "acars"; case MSG_PILOT: return "pilot"; case MSG_TEMP: return "temp"; case MSG_TEMP_SHIP: return "tempship"; case MSG_SAT: return "satellite"; case MSG_POLLUTION: return "pollution"; case MSG_GENERIC: default: return "generic"; } } void Msg::sounding_pack_levels(Msg& dst) const { dst.clear(); dst.type = type; for (size_t i = 0; i < data.size(); ++i) { const msg::Context& ctx = *data[i]; // If it is not a sounding level, just copy it if (ctx.find_vsig() == NULL) { unique_ptr newctx(new msg::Context(ctx)); dst.add_context(std::move(newctx)); continue; } // FIXME: shouldn't this also set significance bits in the output level? for (size_t j = 0; j < ctx.data.size(); ++j) { unique_ptr copy(new Var(*ctx.data[j])); dst.set(std::move(copy), Level(ctx.level.ltype1, ctx.level.l1), ctx.trange); } } } #if 0 void Msg::sounding_unpack_levels(Msg& dst) const { dst.clear(); dst.type = type; for (size_t i = 0; i < data.size(); ++i) { const msg::Context& ctx = *data[i]; const Var* vsig_var = ctx.find_vsig(); if (!vsig_var) { auto_ptr newctx(new msg::Context(ctx)); dst.add_context(newctx); continue; } int vsig = vsig_var->enqi(); if (vsig & VSIG_MISSING) { // If there is no vsig, then we consider it a normal level auto_ptr newctx(new msg::Context(ctx)); dst.add_context(newctx); continue; } /* DBA_RUN_OR_GOTO(fail, dba_var_enqi(msg->data[i].var_press, &press)); */ /* TODO: delete the dba_msg_datum that do not belong in that level */ if (vsig & VSIG_SIGWIND) { auto_ptr copy(new msg::Context(ctx)); copy->level.l2 = 6; dst.add_context(copy); } if (vsig & VSIG_SIGTEMP) { auto_ptr copy(new msg::Context(ctx)); copy->level.l2 = 5; dst.add_context(copy); } if (vsig & VSIG_MAXWIND) { auto_ptr copy(new msg::Context(ctx)); copy->level.l2 = 4; dst.add_context(copy); } if (vsig & VSIG_TROPOPAUSE) { auto_ptr copy(new msg::Context(ctx)); copy->level.l2 = 3; dst.add_context(copy); } if (vsig & VSIG_STANDARD) { auto_ptr copy(new msg::Context(ctx)); copy->level.l2 = 2; dst.add_context(copy); } if (vsig & VSIG_SURFACE) { auto_ptr copy(new msg::Context(ctx)); copy->level.l2 = 1; dst.add_context(copy); } } } #endif MatchedMsg::MatchedMsg(const Msg& m) : m(m) { } MatchedMsg::~MatchedMsg() { } matcher::Result MatchedMsg::match_var_id(int val) const { for (std::vector::const_iterator ci = m.data.begin(); ci != m.data.end(); ++ci) for (std::vector::const_iterator vi = (*ci)->data.begin(); vi != (*ci)->data.end(); ++vi) if (const Var* a = (*vi)->enqa(WR_VAR(0, 33, 195))) if (a->enqi() == val) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedMsg::match_station_id(int val) const { if (const wreport::Var* var = m.get(WR_VAR(0, 1, 192), Level(), Trange())) { return var->enqi() == val ? matcher::MATCH_YES : matcher::MATCH_NO; } else return matcher::MATCH_NA; } matcher::Result MatchedMsg::match_station_wmo(int block, int station) const { const msg::Context* c = m.find_station_context(); if (!c) return matcher::MATCH_NA; if (const wreport::Var* var = c->find_by_id(DBA_MSG_BLOCK)) { // Match block if (var->enqi() != block) return matcher::MATCH_NO; // If station was not requested, we are done if (station == -1) return matcher::MATCH_YES; // Match station if (const wreport::Var* var = c->find_by_id(DBA_MSG_STATION)) { if (var->enqi() != station) return matcher::MATCH_NO; return matcher::MATCH_YES; } } return matcher::MATCH_NA; } matcher::Result MatchedMsg::match_datetime(const DatetimeRange& range) const { Datetime dt = m.get_datetime(); if (dt.is_missing()) return matcher::MATCH_NA; return range.contains(dt) ? matcher::MATCH_YES : matcher::MATCH_NO; } matcher::Result MatchedMsg::match_coords(const LatRange& latrange, const LonRange& lonrange) const { const msg::Context* c = m.find_station_context(); if (!c) return matcher::MATCH_NA; matcher::Result r1 = matcher::MATCH_NA; if (const wreport::Var* var = c->find_by_id(DBA_MSG_LATITUDE)) r1 = latrange.contains(var->enqi()) ? matcher::MATCH_YES : matcher::MATCH_NO; else if (latrange.is_missing()) r1 = matcher::MATCH_YES; matcher::Result r2 = matcher::MATCH_NA; if (const wreport::Var* var = c->find_by_id(DBA_MSG_LONGITUDE)) r2 = lonrange.contains(var->enqi()) ? matcher::MATCH_YES : matcher::MATCH_NO; else if (lonrange.is_missing()) r2 = matcher::MATCH_YES; if (r1 == matcher::MATCH_YES && r2 == matcher::MATCH_YES) return matcher::MATCH_YES; if (r1 == matcher::MATCH_NO || r2 == matcher::MATCH_NO) return matcher::MATCH_NO; return matcher::MATCH_NA; } matcher::Result MatchedMsg::match_rep_memo(const char* memo) const { if (const Var* var = m.get_rep_memo_var()) { if (!var->isset()) return matcher::MATCH_NA; return strcmp(memo, var->enqc()) == 0 ? matcher::MATCH_YES : matcher::MATCH_NO; } else return matcher::MATCH_NA; } MatchedMessages::MatchedMessages(const Messages& m) : m(m) { } MatchedMessages::~MatchedMessages() { } matcher::Result MatchedMessages::match_var_id(int val) const { for (const auto& i: m) if (MatchedMsg(Msg::downcast(i)).match_var_id(val) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedMessages::match_station_id(int val) const { for (const auto& i: m) if (MatchedMsg(Msg::downcast(i)).match_station_id(val) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedMessages::match_station_wmo(int block, int station) const { for (const auto& i: m) if (MatchedMsg(Msg::downcast(i)).match_station_wmo(block, station) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedMessages::match_datetime(const DatetimeRange& range) const { for (const auto& i: m) if (MatchedMsg(Msg::downcast(i)).match_datetime(range) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedMessages::match_coords(const LatRange& latrange, const LonRange& lonrange) const { for (const auto& i: m) if (MatchedMsg(Msg::downcast(i)).match_coords(latrange, lonrange) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } matcher::Result MatchedMessages::match_rep_memo(const char* memo) const { for (const auto& i: m) if (MatchedMsg(Msg::downcast(i)).match_rep_memo(memo) == matcher::MATCH_YES) return matcher::MATCH_YES; return matcher::MATCH_NA; } } dballe-7.7/dballe/msg/wr_codec.h0000644000175000017500000001234112652630043013504 00000000000000#ifndef DBALLE_MSG_WR_CODEC_H #define DBALLE_MSG_WR_CODEC_H #include #include #include #include #include namespace wreport { struct Bulletin; struct Subset; } namespace dballe { struct Msg; namespace msg { struct Context; class WRImporter : public Importer { public: WRImporter(const Options& opts); /** * Import a decoded BUFR/CREX message */ Messages from_bulletin(const wreport::Bulletin& msg) const override; /** * Decode a message from its decoded bulletin, calling \a dest on each * resulting Msg. * * Return false from \a dest to stop decoding. * * @param rmsg * Encoded message. * @retval dest * The function that consumes the decoded messages. * @returns true if it got to the end of decoding, false if dest returned false. */ bool foreach_decoded_bulletin(const wreport::Bulletin& msg, std::function&&)> dest) const; }; class BufrImporter : public WRImporter { public: BufrImporter(const Options& opts=Options()); virtual ~BufrImporter(); bool foreach_decoded(const BinaryMessage& msg, std::function&&)> dest) const override; }; class CrexImporter : public WRImporter { public: CrexImporter(const Options& opts=Options()); virtual ~CrexImporter(); bool foreach_decoded(const BinaryMessage& msg, std::function&&)> dest) const override; }; namespace wr { class Template; } class WRExporter : public Exporter { public: WRExporter(const Options& opts); /** * Import a decoded BUFR/CREX message */ std::unique_ptr to_bulletin(const Messages& msgs) const override; /** * Infer a template name from the message contents */ std::unique_ptr infer_template(const Messages& msgs) const; }; class BufrExporter : public WRExporter { public: BufrExporter(const Options& opts=Options()); virtual ~BufrExporter(); virtual std::string to_binary(const Messages& msgs) const; virtual std::unique_ptr make_bulletin() const; }; class CrexExporter : public WRExporter { public: CrexExporter(const Options& opts=Options()); virtual ~CrexExporter(); virtual std::string to_binary(const Messages& msgs) const; virtual std::unique_ptr make_bulletin() const; }; namespace wr { struct TemplateRegistry; class Template { protected: virtual void setupBulletin(wreport::Bulletin& bulletin); virtual void to_subset(const Msg& msg, wreport::Subset& subset); void add(wreport::Varcode code, const msg::Context* ctx, int shortcut) const; void add(wreport::Varcode code, const msg::Context* ctx, wreport::Varcode srccode) const; void add(wreport::Varcode code, const msg::Context* ctx) const; void add(wreport::Varcode code, int shortcut) const; void add(wreport::Varcode code, wreport::Varcode srccode, const Level& level, const Trange& trange) const; void add(wreport::Varcode code, const wreport::Var* var) const; // Set station name, truncating it if it's too long void do_station_name(wreport::Varcode dstcode) const; /// Find a variable in c_station, or nullptr if not found const wreport::Var* find_station_var(wreport::Varcode code) const; void do_ecmwf_past_wtr() const; void do_station_height() const; // WMO block and station numbers void do_D01001() const; void do_D01004() const; // Date (year, month, day) void do_D01011() const; // Time (hour and minute), return the hour int do_D01012() const; // Time (hour, minute, second) void do_D01013() const; // Latitude and longitude, high accuracy void do_D01021() const; void do_D01022() const; // Latitude and longitude, coarse accuracy void do_D01023() const; public: const Exporter::Options& opts; const Messages& msgs; const Msg* msg = 0; // Msg being read const msg::Context* c_station = 0; const msg::Context* c_gnd_instant = 0; wreport::Subset* subset = 0; // Subset being written Template(const Exporter::Options& opts, const Messages& msgs) : opts(opts), msgs(msgs) {} virtual ~Template() {} virtual const char* name() const = 0; virtual const char* description() const = 0; virtual void to_bulletin(wreport::Bulletin& bulletin); }; struct TemplateFactory { typedef std::function(const Exporter::Options& opts, const Messages& msgs)> factory_func; unsigned data_category = MISSING_INT; std::string name; std::string description; factory_func factory; TemplateFactory(unsigned data_category, std::string name, std::string description, factory_func factory) : data_category(data_category), name(name), description(description), factory(factory) {} }; struct TemplateRegistry : public std::map { static const TemplateRegistry& get(); static const TemplateFactory& get(const std::string& name); void register_factory( unsigned data_category, const std::string& name, const std::string& desc, TemplateFactory::factory_func fac); }; } } } #endif dballe-7.7/dballe/msg/tests-lua.h0000644000175000017500000000316712652630043013646 00000000000000/** * Copyright (C) 2008--2010 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Author: Enrico Zini */ #ifndef WREPORT_TEST_UTILS_LUA_H #define WREPORT_TEST_UTILS_LUA_H extern "C" { #include #include } #include #include namespace dballe { namespace tests { struct Lua { lua_State *L; std::string m_filename; Lua(const std::string& src = std::string()); ~Lua(); /// Load the test code from the given file void loadFile(const std::string& fname); /// Load the test code from the given string containing Lua source code void loadString(const std::string& buf); /// Runs the parsed code to let it define the 'test' function we are going /// to use void create_lua_object(); /// Send Lua's print output to an ostream void captureOutput(std::ostream& buf); /// Run the 'test' function and return its result, as a string std::string run(); }; } } #endif dballe-7.7/dballe/msg/wr_export-test.cc0000644000175000017500000010066612652630043015073 00000000000000#include "tests.h" #include "wr_codec.h" #include "msg.h" #include "context.h" #include #include #include #include #include #include using namespace wreport; using namespace std; using namespace dballe; using namespace dballe::tests; using namespace dballe::tests::tweaks; namespace { using dballe::tests::TestCodec; class Tests : public TestCase { using TestCase::TestCase; void add_testcodec(const char* fname, std::function method) { add_method(fname, [=]() { string pathname = "bufr/"; pathname += fname; dballe::tests::TestCodec test(pathname); method(test); }); } void register_tests() override { add_method("all_bufr", []() { // Test that plain re-export of all our BUFR test files is possible // note: These were blacklisted: // "bufr/obs3-3.1.bufr", // "bufr/obs3-56.2.bufr", // "bufr/test-buoy1.bufr", // "bufr/test-soil1.bufr", set bl_crex; // CREX tables do not contain the entries needed to encode pollution // messages bl_crex.insert("bufr/ed4.bufr"); const char** files = dballe::tests::bufr_files; vector fails; int i; for (i = 0; files[i] != NULL; i++) { try { Messages msgs = read_msgs(files[i], File::BUFR); wassert(actual(msgs.size()) > 0); std::unique_ptr exporter; exporter = msg::Exporter::create(File::BUFR/*, const Options& opts=Options()*/); unique_ptr bbulletin = exporter->to_bulletin(msgs); if (bl_crex.find(files[i]) == bl_crex.end()) { exporter = msg::Exporter::create(File::CREX/*, const Options& opts=Options()*/); unique_ptr cbulletin = exporter->to_bulletin(msgs); } } catch (std::exception& e) { fails.push_back(string(files[i]) + ": " + e.what()); } } if (!fails.empty()) { std::stringstream ss; ss << fails.size() << "/" << i << " errors:" << endl; ss << str::join("\n", fails.begin(), fails.end()); throw TestFailed(ss.str()); } }); add_method("all_crex", []() { // Test that plain re-export of all our CREX test files is possible const char** files = dballe::tests::crex_files; vector fails; int i; for (i = 0; files[i] != NULL; i++) { try { Messages msgs = read_msgs(files[i], File::CREX); wassert(actual(msgs.size()) > 0); std::unique_ptr exporter = msg::Exporter::create(File::BUFR/*, const Options& opts=Options()*/); unique_ptr bbulletin = exporter->to_bulletin(msgs); exporter = msg::Exporter::create(File::CREX/*, const Options& opts=Options()*/); unique_ptr cbulletin = exporter->to_bulletin(msgs); } catch (std::exception& e) { fails.push_back(string(files[i]) + ": " + e.what()); } } if (!fails.empty()) { std::stringstream ss; ss << fails.size() << "/" << i << " errors:" << endl; ss << str::join("\n", fails.begin(), fails.end()); throw TestFailed(ss.str()); } }); add_method("reproduce_temp", []() { // Export a well known TEMP which used to fail Messages msgs = read_msgs_csv("csv/temp1.csv"); wassert(actual(msgs.size()) > 0); // Replace with packed levels because comparison later happens against // packed levels { unique_ptr msg(new Msg); msg->sounding_pack_levels(Msg::downcast(msgs[0])); msgs.clear(); msgs.append(move(msg)); } // Export to BUFR std::unique_ptr bufr_exporter(msg::Exporter::create(File::BUFR/*, const Options& opts=Options()*/)); unique_ptr bbulletin = bufr_exporter->to_bulletin(msgs); // Import and check the differences { std::unique_ptr bufr_importer(msg::Importer::create(File::BUFR/*, const Options& opts=Options()*/)); Messages msgs1 = wcallchecked(bufr_importer->from_bulletin(*bbulletin)); notes::Collect c(cerr); wassert(actual(msgs.diff(msgs1)) == 0); } // Export to CREX std::unique_ptr crex_exporter(msg::Exporter::create(File::CREX/*, const Options& opts=Options()*/)); unique_ptr cbulletin = crex_exporter->to_bulletin(msgs); // Import and check the differences { std::unique_ptr crex_importer(msg::Importer::create(File::CREX/*, const Options& opts=Options()*/)); Messages msgs1 = wcallchecked(crex_importer->from_bulletin(*cbulletin)); notes::Collect c(cerr); wassert(actual(msgs.diff(msgs1)) == 0); } }); // Re-export tests for old style synops add_testcodec("obs0-1.22.bufr", [](TestCodec& test) { test.expected_min_vars = 34; test.configure_ecmwf_to_wmo_tweaks(); wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); test.after_convert_reimport.add(new StripDatetimeVars()); wassert(test.run_convert("synop")); }); add_testcodec("obs0-1.11188.bufr", [](TestCodec& test) { test.expected_subsets = 1; test.expected_min_vars = 10; wassert(test.run_reimport()); wassert(test.run_convert("synop-ecmwf")); }); add_testcodec("obs0-3.504.bufr", [](TestCodec& test) { test.expected_subsets = 1; test.expected_min_vars = 10; wassert(test.run_reimport()); wassert(test.run_convert("synop-ecmwf")); }); // Re-export test for new style synops add_testcodec("synop-cloudbelow.bufr", [](TestCodec& test) { test.expected_subsets = 22; test.expected_min_vars = 10; test.expected_data_category = 0; test.expected_data_subcategory = 1; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-evapo.bufr", [](TestCodec& test) { test.expected_subsets = 14; test.expected_min_vars = 10; test.expected_data_category = 0; test.expected_data_subcategory = 2; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-groundtemp.bufr", [](TestCodec& test) { test.expected_subsets = 26; test.expected_min_vars = 10; test.expected_data_category = 0; test.expected_data_subcategory = 1; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-longname.bufr", [](TestCodec& test) { test.after_reimport_reimport.add(new TruncStName()); test.after_convert_reimport.add(new TruncStName()); test.expected_subsets = 7; test.expected_min_vars = 10; test.expected_data_category = 0; test.expected_data_subcategory = 1; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-oddgust.bufr", [](TestCodec& test) { test.expected_subsets = 26; test.expected_min_vars = 10; test.expected_data_category = 0; test.expected_data_subcategory = 0; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-oddprec.bufr", [](TestCodec& test) { test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 0; test.expected_data_subcategory = 0; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-strayvs.bufr", [](TestCodec& test) { test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 0; test.expected_data_subcategory = 1; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-sunshine.bufr", [](TestCodec& test) { test.expected_subsets = 26; test.expected_min_vars = 10; test.expected_data_category = 0; test.expected_data_subcategory = 1; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-gtscosmo.bufr", [](TestCodec& test) { test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 0; test.expected_data_subcategory = 2; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-rad1.bufr", [](TestCodec& test) { // Test import/export of GTS synop with radiation information test.expected_subsets = 25; test.expected_min_vars = 50; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-rad2.bufr", [](TestCodec& test) { // Test import/export of GTS synop without pressure of standard level // FIXME: currently fails test.expected_template = "synop-wmo"; test.expected_min_vars = 50; //test.verbose = true; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("synop-tchange.bufr", [](TestCodec& test) { // Test import/export of GTS synop with temperature change information test.expected_min_vars = 50; wassert(test.run_reimport()); wassert(test.run_convert("synop-wmo")); }); add_testcodec("temp-timesig18.bufr", [](TestCodec& test) { // FIXME: temp message with data category 0: what do we do with it? // FIXME: currently fails test.expected_min_vars = 50; test.expected_template = "temp-wmo"; wassert(test.run_reimport()); wassert(test.run_convert("temp-wmo")); }); add_testcodec("obs2-101.16.bufr", [](TestCodec& test) { // Re-export test for old style temps wassert(test.run_reimport()); wassert(test.run_convert("temp-ecmwf")); }); add_testcodec("obs2-102.1.bufr", [](TestCodec& test) { wassert(test.run_reimport()); wassert(test.run_convert("temp-ecmwf")); }); add_testcodec("obs2-91.2.bufr", [](TestCodec& test) { wassert(test.run_reimport()); wassert(test.run_convert("pilot-ecmwf")); }); add_testcodec("temp-bad3.bufr", [](TestCodec& test) { wassert(test.run_reimport()); wassert(test.run_convert("temp")); }); add_testcodec("temp-bad5.bufr", [](TestCodec& test) { // This has some sounding groups with undefined VSS wassert(test.run_reimport()); wassert(test.run_convert("temp-ecmwf")); }); add_testcodec("test-temp1.bufr", [](TestCodec& test) { // This has some sounding groups with undefined VSS, and an unusual template wassert(test.run_reimport()); wassert(test.run_convert("temp-ecmwf")); }); add_testcodec("C23000.bufr", [](TestCodec& test) { // This has an unusual template test.after_reimport_import.add(new StripSubstituteAttrs()); test.after_convert_import.add(new StripSubstituteAttrs()); wassert(test.run_reimport()); wassert(test.run_convert("temp-ecmwf")); }); add_testcodec("temp-bad1.bufr", [](TestCodec& test) { test.after_reimport_reimport.add(new StripQCAttrs()); test.after_reimport_reimport.add(new StripSubstituteAttrs()); test.after_reimport_reimport.add(new StripDatetimeVars()); test.after_convert_import.add(new StripQCAttrs()); test.after_convert_import.add(new StripSubstituteAttrs()); test.after_convert_import.add(new StripDatetimeVars()); test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 2; test.expected_data_subcategory = 255; test.expected_data_subcategory_local = 101; wassert(test.run_reimport()); wassert(test.run_convert("temp-ecmwf")); }); add_testcodec("temp-bad2.bufr", [](TestCodec& test) { test.after_reimport_reimport.add(new StripQCAttrs()); test.after_reimport_reimport.add(new StripSubstituteAttrs()); test.after_reimport_reimport.add(new StripDatetimeVars()); test.after_convert_import.add(new StripQCAttrs()); test.after_convert_import.add(new StripSubstituteAttrs()); test.after_convert_import.add(new StripDatetimeVars()); test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 2; test.expected_data_subcategory = 255; test.expected_data_subcategory_local = 101; wassert(test.run_reimport()); wassert(test.run_convert("temp-ecmwf")); }); add_testcodec("temp-gts1.bufr", [](TestCodec& test) { // Re-export test for new style temps test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 2; test.expected_data_subcategory = 4; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("temp-wmo")); }); add_testcodec("temp-gts2.bufr", [](TestCodec& test) { test.expected_subsets = 6; test.expected_min_vars = 10; test.expected_data_category = 2; test.expected_data_subcategory = 4; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("temp-wmo")); }); add_testcodec("temp-gts3.bufr", [](TestCodec& test) { test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 2; test.expected_data_subcategory = 4; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("temp-wmo")); }); add_testcodec("temp-gtscosmo.bufr", [](TestCodec& test) { test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 2; test.expected_data_subcategory = 4; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("temp-wmo")); }); #if 0 Test("new_temp5", [](Fixture& f) { #warning This is importer with height above ground levels, but exported with pressure levels // Another weird template BufrReimportTest test("bufr/temp-2-255.bufr"); run_test(test, do_wmo, "temp"); //test.output_opts.template_name = "temp-wmo"; //run_test(test, do_test, "auto"); //test.output_opts.template_name = "temp-ecmwf"; //test.clear_tweaks(); //run_test(test, do_test, "old"); }); #endif add_testcodec("temp-bad4.bufr", [](TestCodec& test) { test.after_reimport_reimport.add(new RoundLegacyVars()); test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 2; test.expected_data_subcategory = 255; test.expected_data_subcategory_local = 101; wassert(test.run_reimport()); wassert(test.run_convert("temp-wmo")); }); #if 0 Test("new_temp8", [](Fixture& f) { #warning There is no template that can export these forecast TEMPs except generic // generic temp with forecast info and hybrid levels (?) BufrReimportTest test("bufr/tempforecast.bufr"); run_test(test, do_test, "temp-wmo"); test.clear_tweaks(); test.tweaks.push_back(new StripQCAttrs()); run_test(test, do_test, "temp-ecmwf", "temp-wmo"); }); #endif add_testcodec("vad.bufr", [](TestCodec& test) { // Test that temp vad subtype is set correctly test.expected_subsets = 1; test.expected_min_vars = 10; test.expected_data_category = 6; test.expected_data_subcategory = 1; test.expected_data_subcategory_local = 255; wassert(test.run_reimport()); wassert(test.run_convert("temp")); }); add_testcodec("temp-huge.bufr", [](TestCodec& test) { // Test correct import/export of a temp with thousands of levels test.expected_min_vars = 30000; wassert(test.run_reimport()); wassert(test.run_convert("temp-wmo")); }); // New style ACARS #if 0 Test("new_acars1", [](Fixture& f) { #warning no documentation on new stile ACARS available yet //BufrReimportTest test("bufr/gts-acars1.bufr"); //run_test(test, do_test, "acars-wmo"); }); Test("new_acars2", [](Fixture& f) { #warning no documentation on new stile ACARS available yet //BufrReimportTest test("bufr/gts-acars2.bufr"); //run_test(test, do_test, "acars-wmo"); }); Test("new_acars3", [](Fixture& f) { #warning no documentation on new stile ACARS available yet //BufrReimportTest test("bufr/gts-acars-uk1.bufr"); //run_test(test, do_test, "acars-wmo"); }); Test("new_acars4", [](Fixture& f) { #warning no documentation on new stile ACARS available yet //BufrReimportTest test("bufr/gts-acars-us1.bufr"); //run_test(test, do_test, "acars-wmo"); }); #endif // New style AMDAR add_testcodec("gts-amdar1.bufr", [](TestCodec& test) { // FIXME: currently fails wassert(test.run_reimport()); wassert(test.run_convert("amdar-wmo")); }); add_testcodec("gts-amdar2.bufr", [](TestCodec& test) { // FIXME: currently fails wassert(test.run_reimport()); wassert(test.run_convert("amdar-wmo")); }); // Re-export to BUFR (simplified, full template autodetect) and see the differences add_method("all_simplified", []() { const char** files = dballe::tests::bufr_files; // Uncomment to single out one failing file //const char* files[] = { "bufr/temp-2-255.bufr", NULL }; set blacklist; // Generics, would need a template override to avoid the per-rete // autodetected export blacklist.insert("bufr/tempforecast.bufr"); blacklist.insert("bufr/obs255-255.0.bufr"); // Nonstandard messages that need tweaks, tested individually above blacklist.insert("bufr/test-temp1.bufr"); blacklist.insert("bufr/C23000.bufr"); blacklist.insert("bufr/temp-2-255.bufr"); blacklist.insert("bufr/synop-longname.bufr"); blacklist.insert("bufr/temp-bad4.bufr"); vector fails; int i; std::unique_ptr exporter; exporter = msg::Exporter::create(File::BUFR/*, const Options& opts=Options()*/); std::unique_ptr importer = msg::Importer::create(File::BUFR/*, opts*/); for (i = 0; files[i] != NULL; i++) { if (blacklist.find(files[i]) != blacklist.end()) continue; try { // Import Messages msgs = read_msgs(files[i], File::BUFR); wassert(actual(msgs.size()) > 0); // Export unique_ptr bbulletin = exporter->to_bulletin(msgs); // Import again Messages msgs1 = importer->from_bulletin(*bbulletin); // Compare notes::Collect c(cerr); int diffs = msgs.diff(msgs1); if (diffs) { FILE* out1 = fopen("/tmp/msg1.txt", "w"); FILE* out2 = fopen("/tmp/msg2.txt", "w"); msgs.print(out1); msgs1.print(out2); fclose(out1); fclose(out2); } wassert(actual(diffs) == 0); } catch (std::exception& e) { fails.push_back(string(files[i]) + ": " + e.what()); } } if (!fails.empty()) { std::stringstream ss; ss << fails.size() << "/" << i << " errors:" << endl; ss << str::join("\n", fails.begin(), fails.end()); throw TestFailed(ss.str()); } }); add_method("all_precise", []() { // Re-export to BUFR (not simplified, full template autodetect) and see the differences const char** files = dballe::tests::bufr_files; // Uncomment to single out one failing file //const char* files[] = { "bufr/obs0-1.22.bufr", NULL }; set blacklist; // Generics, would need a template override to avoid the per-rete // autodetected export blacklist.insert("bufr/tempforecast.bufr"); blacklist.insert("bufr/obs255-255.0.bufr"); // Nonstandard messages that need tweaks, tested individually above blacklist.insert("bufr/test-temp1.bufr"); blacklist.insert("bufr/C23000.bufr"); blacklist.insert("bufr/temp-2-255.bufr"); blacklist.insert("bufr/synop-longname.bufr"); blacklist.insert("bufr/temp-bad4.bufr"); vector fails; int i; std::unique_ptr exporter; exporter = msg::Exporter::create(File::BUFR/*, const Options& opts=Options()*/); msg::Importer::Options import_opts; import_opts.simplified = false; std::unique_ptr importer = msg::Importer::create(File::BUFR, import_opts); for (i = 0; files[i] != NULL; i++) { if (blacklist.find(files[i]) != blacklist.end()) continue; try { // Import Messages msgs = read_msgs(files[i], File::BUFR, import_opts); wassert(actual(msgs.size()) > 0); // Export unique_ptr bbulletin = exporter->to_bulletin(msgs); // Import again Messages msgs1 = importer->from_bulletin(*bbulletin); // Compare stringstream str; notes::Collect c(str); int diffs = msgs.diff(msgs1); if (diffs) { string tag = str::basename(files[i]); dballe::tests::dump("dballe-orig-" + tag, msgs, "original message"); dballe::tests::dump("dballe-reenc-" + tag, *bbulletin, "reencoded message"); dballe::tests::dump("dballe-reenc-" + tag, msgs1, "decoded reencoded message"); dballe::tests::dump("dballe-diffs-" + tag, str.str(), "differences"); } wassert(actual(diffs) == 0); } catch (std::exception& e) { fails.push_back(string(files[i]) + ": " + e.what()); } } if (!fails.empty()) { std::stringstream ss; ss << fails.size() << "/" << i << " errors:" << endl; ss << str::join("\n", fails.begin(), fails.end()); throw TestFailed(ss.str()); } }); // Old PILOT add_method("old_pilot1", []() { // Test that pilot subtype is set correctly Messages msgs = read_msgs("bufr/obs2-91.2.bufr", File::BUFR); msg::Exporter::Options opts; opts.template_name = "pilot-wmo"; unique_ptr bulletin = test_export_msgs(File::BUFR, msgs, "pilotwmo", opts); wassert(actual(bulletin->data_category) == 2); wassert(actual(bulletin->data_subcategory) == 1); wassert(actual(bulletin->data_subcategory_local) == 255); }); add_testcodec("pilot-gts3.bufr", [](TestCodec& test) { // Test import/export of ECMWF pilot with pressure levels test.expected_min_vars = 50; test.configure_ecmwf_to_wmo_tweaks(); wassert(test.run_reimport()); wassert(test.run_convert("pilot-wmo")); }); add_testcodec("pilot-gts4.bufr", [](TestCodec& test) { // Test import/export of ECMWF pilot with geopotential levels test.expected_min_vars = 50; test.configure_ecmwf_to_wmo_tweaks(); test.after_convert_reimport.add(new dballe::tests::tweaks::HeightToGeopotential); test.after_convert_reimport.add(new dballe::tests::tweaks::RemoveContext( Level(100, 70000), Trange::instant())); test.after_convert_reimport.add(new dballe::tests::tweaks::RemoveContext( Level(100, 85000), Trange::instant())); wassert(test.run_reimport()); wassert(test.run_convert("pilot-wmo")); }); // New style PILOT add_testcodec("pilot-gts1.bufr", [](TestCodec& test) { test.expected_data_category = 2; test.expected_data_subcategory = 1; test.expected_data_subcategory_local = 211; wassert(test.run_reimport()); wassert(test.run_convert("pilot-wmo")); }); add_testcodec("pilot-ecmwf-geopotential.bufr", [](TestCodec& test) { test.configure_ecmwf_to_wmo_tweaks(); test.after_reimport_reimport.add(new StripVars({ WR_VAR(0, 10, 8) })); test.after_convert_reimport.add(new StripVars({ WR_VAR(0, 10, 8) })); test.expected_min_vars = 30; wassert(test.run_reimport()); wassert(test.run_convert("pilot-wmo")); }); add_method("new_pilot4", []() { // Test for a bug where geopotential levels became pressure levels Messages msgs1 = read_msgs("bufr/pilot-ecmwf-geopotential.bufr", File::BUFR); wassert(actual(msgs1.size()) == 1); Msg& msg1 = Msg::downcast(msgs1[0]); // Geopotential levels are converted to height above msl const msg::Context* c = msg1.find_context(Level(102, 900), Trange(254, 0, 0)); wassert(actual(c).istrue()); // Convert to WMO template msg::Exporter::Options output_opts; output_opts.template_name = "pilot-wmo"; //if (verbose) cerr << "Exporting " << output_opts.to_string() << endl; std::unique_ptr bulletin = test_export_msgs(File::BUFR, msgs1, "towmo", output_opts); // Import again std::unique_ptr imp = msg::Importer::create(File::BUFR); Messages msgs2 = imp->from_bulletin(*bulletin); wassert(actual(msgs2.size()) == 1); Msg& msg2 = Msg::downcast(msgs2[0]); // Ensure we didn't get pressure levels wassert(actual(msg2.find_context(Level(100, 900), Trange(254, 0, 0))).isfalse()); }); add_method("new_pilot5", []() { // Test for a range error in one specific BUFR Messages msgs1 = read_msgs("bufr/temp-2-255.bufr", File::BUFR); wassert(actual(msgs1.size()) == 1); // Convert to CREX msg::Exporter::Options output_opts; output_opts.template_name = "temp-wmo"; std::unique_ptr bulletin = test_export_msgs(File::CREX, msgs1, "tocrex", output_opts); // Import again std::unique_ptr imp = msg::Importer::create(File::BUFR); Messages msgs2 = wcallchecked(imp->from_bulletin(*bulletin)); wassert(actual(msgs2.size()) == 1); }); // Old SHIP add_method("old_ship1", []() { // Test that temp ship subtype is set correctly Messages msgs = read_msgs("bufr/obs2-102.1.bufr", File::BUFR); msg::Exporter::Options opts; opts.template_name = "temp-wmo"; unique_ptr bulletin = test_export_msgs(File::BUFR, msgs, "tempship", opts); wassert(actual(bulletin->data_category) == 2); wassert(actual(bulletin->data_subcategory) == 5); wassert(actual(bulletin->data_subcategory_local) == 255); }); add_testcodec("ecmwf-ship-1-11.bufr", [](TestCodec& test) { // Test import/export of ECMWF synop ship test.expected_min_vars = 34; test.configure_ecmwf_to_wmo_tweaks(); wassert(test.run_reimport()); wassert(test.run_convert("ship-wmo")); }); add_testcodec("ecmwf-ship-1-12.bufr", [](TestCodec& test) { // Test import/export of ECMWF synop ship record 2 test.expected_min_vars = 21; test.configure_ecmwf_to_wmo_tweaks(); wassert(test.run_reimport()); wassert(test.run_convert("ship-wmo")); }); add_testcodec("ecmwf-ship-1-13.bufr", [](TestCodec& test) { // Test import/export of ECMWF synop ship (auto) test.expected_min_vars = 30; test.configure_ecmwf_to_wmo_tweaks(); wassert(test.run_reimport()); wassert(test.run_convert("ship-wmo")); }); add_testcodec("ecmwf-ship-1-14.bufr", [](TestCodec& test) { // Test import/export of ECMWF synop ship (auto) record 2 test.expected_min_vars = 28; test.configure_ecmwf_to_wmo_tweaks(); wassert(test.run_reimport()); wassert(test.run_convert("ship-wmo")); }); // New SHIP add_testcodec("wmo-ship-1.bufr", [](TestCodec& test) { // Test import/export of WMO synop ship test.expected_min_vars = 50; wassert(test.run_reimport()); wassert(test.run_convert("ship-wmo")); }); // ECMWF <-> WMO add_testcodec("ecmwf-amdar1.bufr", [](TestCodec& test) { test.expected_min_vars = 21; wassert(test.run_reimport()); wassert(test.run_convert("amdar")); }); add_testcodec("ecmwf-acars1.bufr", [](TestCodec& test) { test.expected_min_vars = 21; wassert(test.run_reimport()); wassert(test.run_convert("acars")); }); } } test("msg_wr_export"); } dballe-7.7/dballe/msg/msg-lua.cc0000644000175000017500000001363412652630043013430 00000000000000/* * Copyright (C) 2010 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "config.h" #include "msg.h" #include "context.h" #include "dballe/msg/vars.h" #include "wreport/utils/lua.h" using namespace wreport; using namespace std; namespace dballe { #ifdef HAVE_LUA static Varcode dbalua_to_varcode(lua_State* L, int idx) { const char* str = lua_tostring(L, idx); if (str == NULL) return 0; else return varcode_parse(str); } static int dbalua_msg_type(lua_State *L) { Msg* msg = Msg::lua_check(L, 1); lua_pushstring(L, msg_type_name(msg->type)); return 1; } static int dbalua_msg_size(lua_State *L) { Msg* msg = Msg::lua_check(L, 1); lua_pushinteger(L, msg->data.size()); return 1; } static int dbalua_msg_foreach(lua_State *L) { Msg* msg = Msg::lua_check(L, 1); for (size_t i = 0; i < msg->data.size(); ++i) { lua_pushvalue(L, -1); msg->data[i]->lua_push(L); /* Do the call (1 argument, 0 results) */ if (lua_pcall(L, 1, 0, 0) != 0) lua_error(L); } return 0; } static int dbalua_msg_find(lua_State *L) { Msg* msg = Msg::lua_check(L, 1); Var* res = NULL; if (lua_gettop(L) == 2) { // By ID size_t len; const char* name = lua_tolstring(L, 2, &len); int id = resolve_var_substring(name, len); res = msg->edit_by_id(id); } else { // By all details Varcode code = dbalua_to_varcode(L, 2); Level level; level.ltype1 = lua_isnil(L, 3) ? MISSING_INT : lua_tointeger(L, 3); level.l1 = lua_isnil(L, 4) ? MISSING_INT : lua_tointeger(L, 4); level.ltype2 = lua_isnil(L, 5) ? MISSING_INT : lua_tointeger(L, 5); level.l2 = lua_isnil(L, 6) ? MISSING_INT : lua_tointeger(L, 6); Trange trange; trange.pind = lua_isnil(L, 7) ? MISSING_INT : lua_tointeger(L, 7); trange.p1 = lua_isnil(L, 8) ? MISSING_INT : lua_tointeger(L, 8); trange.p2 = lua_isnil(L, 9) ? MISSING_INT : lua_tointeger(L, 9); res = msg->edit(code, level, trange); } if (res == NULL) lua_pushnil(L); else res->lua_push(L); return 1; } static int dbalua_msg_tostring(lua_State *L) { Msg* msg = Msg::lua_check(L, 1); int varcount = 0; for (size_t i = 0; i < msg->data.size(); ++i) varcount += msg->data[i]->data.size(); lua_pushfstring(L, "dba_msg(%s, %d ctx, %d vars)", msg_type_name(msg->type), msg->data.size(), varcount); return 1; } static const struct luaL_Reg dbalua_msg_lib [] = { { "type", dbalua_msg_type }, { "size", dbalua_msg_size }, { "foreach", dbalua_msg_foreach }, { "find", dbalua_msg_find }, { "__tostring", dbalua_msg_tostring }, {NULL, NULL} }; void Msg::lua_push(struct lua_State* L) { lua::push_object(L, this, "dballe.msg", dbalua_msg_lib); } Msg* Msg::lua_check(struct lua_State* L, int idx) { Msg** v = (Msg**)luaL_checkudata(L, idx, "dballe.msg"); return (v != NULL) ? *v : NULL; } static int dbalua_msg_context_size(lua_State *L) { msg::Context* ctx = msg::Context::lua_check(L, 1); lua_pushinteger(L, ctx->data.size()); return 1; } static int dbalua_msg_context_foreach(lua_State *L) { msg::Context* ctx = msg::Context::lua_check(L, 1); for (size_t i = 0; i < ctx->data.size(); ++i) { lua_pushvalue(L, -1); ctx->data[i]->lua_push(L); /* do the call (1 argument, 0 results) */ if (lua_pcall(L, 1, 0, 0) != 0) lua_error(L); } return 0; } static int dbalua_msg_context_tostring(lua_State *L) { msg::Context* ctx = msg::Context::lua_check(L, 1); lua_pushfstring(L, "dba_msg_context(%d vars)", ctx->data.size()); return 1; } #define make_accessor(name, acc) static int dbalua_msg_context_##name(lua_State *L) { \ msg::Context* ctx = msg::Context::lua_check(L, 1); \ lua_pushinteger(L, ctx->acc); \ return 1; \ } make_accessor(ltype1, level.ltype1) make_accessor(l1, level.l1) make_accessor(ltype2, level.ltype2) make_accessor(l2, level.l2) make_accessor(pind, trange.pind) make_accessor(p1, trange.p1) make_accessor(p2, trange.p2) #undef make_accessor static const struct luaL_Reg dbalua_msg_context_lib [] = { { "ltype1", dbalua_msg_context_ltype1 }, { "l1", dbalua_msg_context_l1 }, { "ltype2", dbalua_msg_context_ltype2 }, { "l2", dbalua_msg_context_l2 }, { "pind", dbalua_msg_context_pind }, { "p1", dbalua_msg_context_p1 }, { "p2", dbalua_msg_context_p2 }, { "size", dbalua_msg_context_size }, { "foreach", dbalua_msg_context_foreach }, { "__tostring", dbalua_msg_context_tostring }, {NULL, NULL} }; void msg::Context::lua_push(struct lua_State* L) { lua::push_object(L, this, "dballe.msg.context", dbalua_msg_context_lib); } msg::Context* msg::Context::lua_check(struct lua_State* L, int idx) { msg::Context** v = (msg::Context**)luaL_checkudata(L, idx, "dballe.msg.context"); return (v != NULL) ? *v : NULL; } #else void Msg::lua_push(struct lua_State* L) { throw error_unimplemented("DB-All.e compiled without Lua support"); } Msg* Msg::lua_check(struct lua_State* L, int idx) { throw error_unimplemented("DB-All.e compiled without Lua support"); } void msg::Context::lua_push(struct lua_State* L) { throw error_unimplemented("DB-All.e compiled without Lua support"); } msg::Context* msg::Context::lua_check(struct lua_State* L, int idx) { throw error_unimplemented("DB-All.e compiled without Lua support"); } #endif } // namespace dballe dballe-7.7/dballe/msg/wr_codec.cc0000644000175000017500000003457112652630043013653 00000000000000#include "wr_codec.h" #include "msg.h" #include "context.h" #include "wr_importers/base.h" #include #include using namespace wreport; using namespace std; namespace dballe { namespace msg { WRImporter::WRImporter(const Options& opts) : Importer(opts) {} BufrImporter::BufrImporter(const Options& opts) : WRImporter(opts) {} BufrImporter::~BufrImporter() {} bool BufrImporter::foreach_decoded(const BinaryMessage& msg, std::function&&)> dest) const { unique_ptr bulletin(BufrBulletin::decode(msg.data)); return foreach_decoded_bulletin(*bulletin, dest); } CrexImporter::CrexImporter(const Options& opts) : WRImporter(opts) {} CrexImporter::~CrexImporter() {} bool CrexImporter::foreach_decoded(const BinaryMessage& msg, std::function&&)> dest) const { unique_ptr bulletin(CrexBulletin::decode(msg.data)); return foreach_decoded_bulletin(*bulletin, dest); } Messages WRImporter::from_bulletin(const wreport::Bulletin& msg) const { Messages res; foreach_decoded_bulletin(msg, [&](unique_ptr&& m) { res.append(move(m)); return true; }); return res; } bool WRImporter::foreach_decoded_bulletin(const wreport::Bulletin& msg, std::function&&)> dest) const { // Infer the right importer. See Common Code Table C-13 std::unique_ptr importer; switch (msg.data_category) { // Surface data - land case 0: switch (msg.data_subcategory) { // Routine aeronautical observations (METAR) case 10: importer = wr::Importer::createMetar(opts); break; default: // Old ECMWF METAR type if (msg.data_subcategory_local == 140) importer = wr::Importer::createMetar(opts); else importer = wr::Importer::createSynop(opts); break; } break; // Surface data - sea case 1: importer = wr::Importer::createShip(opts); break; // Vertical soundings (other than satellite) case 2: importer = wr::Importer::createTemp(opts); break; // Vertical soundings (satellite) case 3: importer = wr::Importer::createSat(opts); break; // Single level upper-air data (other than satellite) case 4: importer = wr::Importer::createFlight(opts); break; // Radar data case 6: if (msg.data_subcategory == 1) // Doppler wind profiles importer = wr::Importer::createTemp(opts); else importer = wr::Importer::createGeneric(opts); break; // Physical/chemical constituents case 8: importer = wr::Importer::createPollution(opts); break; default: importer = wr::Importer::createGeneric(opts); break; } MsgType type = importer->scanType(msg); for (unsigned i = 0; i < msg.subsets.size(); ++i) { std::unique_ptr newmsg(new Msg); newmsg->type = type; importer->import(msg.subsets[i], *newmsg); if (!dest(move(newmsg))) return false; } return true; } WRExporter::WRExporter(const Options& opts) : Exporter(opts) {} BufrExporter::BufrExporter(const Options& opts) : WRExporter(opts) {} BufrExporter::~BufrExporter() {} std::unique_ptr BufrExporter::make_bulletin() const { return std::unique_ptr(BufrBulletin::create().release()); } std::string BufrExporter::to_binary(const Messages& msgs) const { return to_bulletin(msgs)->encode(); } CrexExporter::CrexExporter(const Options& opts) : WRExporter(opts) {} CrexExporter::~CrexExporter() {} std::unique_ptr CrexExporter::make_bulletin() const { return std::unique_ptr(CrexBulletin::create().release()); } std::string CrexExporter::to_binary(const Messages& msgs) const { return to_bulletin(msgs)->encode(); } namespace { const char* infer_from_message(const Msg& msg) { switch (msg.type) { case MSG_TEMP_SHIP: return "temp-ship"; default: break; } return msg_type_name(msg.type); } } unique_ptr WRExporter::infer_template(const Messages& msgs) const { // Select initial template name string tpl = opts.template_name; if (tpl.empty()) tpl = infer_from_message(Msg::downcast(msgs[0])); // Get template factory const wr::TemplateFactory& fac = wr::TemplateRegistry::get(tpl); return fac.factory(opts, msgs); } unique_ptr WRExporter::to_bulletin(const Messages& msgs) const { std::unique_ptr encoder = infer_template(msgs); // fprintf(stderr, "Encoding with template %s\n", encoder->name()); auto res = make_bulletin(); encoder->to_bulletin(*res); return res; } namespace wr { extern void register_synop(TemplateRegistry&); extern void register_ship(TemplateRegistry&); extern void register_buoy(TemplateRegistry&); extern void register_metar(TemplateRegistry&); extern void register_temp(TemplateRegistry&); extern void register_flight(TemplateRegistry&); extern void register_generic(TemplateRegistry&); extern void register_pollution(TemplateRegistry&); static TemplateRegistry* registry = NULL; const TemplateRegistry& TemplateRegistry::get() { if (!registry) { registry = new TemplateRegistry; registry->register_factory(MISSING_INT, "wmo", "WMO style templates (autodetect)", [](const Exporter::Options& opts, const Messages& msgs) { const Msg& msg = Msg::downcast(msgs[0]); string tpl; switch (msg.type) { case MSG_TEMP_SHIP: tpl = "temp-wmo"; break; default: tpl = msg_type_name(msg.type); tpl += "-wmo"; break; } const wr::TemplateFactory& fac = wr::TemplateRegistry::get(tpl); return fac.factory(opts, msgs); }); // Populate it register_synop(*registry); register_ship(*registry); register_buoy(*registry); register_metar(*registry); register_temp(*registry); register_flight(*registry); register_generic(*registry); register_pollution(*registry); // registry->insert("synop", ...) // registry->insert("synop-high", ...) // registry->insert("wmo-synop", ...) // registry->insert("wmo-synop-high", ...) // registry->insert("ecmwf-synop", ...) // registry->insert("ecmwf-synop-high", ...) } return *registry; } const TemplateFactory& TemplateRegistry::get(const std::string& name) { const TemplateRegistry& tr = get(); TemplateRegistry::const_iterator i = tr.find(name); if (i == tr.end()) error_notfound::throwf("requested export template %s which does not exist", name.c_str()); return i->second; } void TemplateRegistry::register_factory( unsigned data_category, const std::string& name, const std::string& desc, TemplateFactory::factory_func fac) { insert(make_pair(name, TemplateFactory(data_category, name, desc, fac))); } void Template::to_bulletin(wreport::Bulletin& bulletin) { setupBulletin(bulletin); for (unsigned i = 0; i < msgs.size(); ++i) { Subset& s = bulletin.obtain_subset(i); to_subset(Msg::downcast(msgs[i]), s); } } void Template::setupBulletin(wreport::Bulletin& bulletin) { // Get reference time from first msg in the set // If not found, use current time. Datetime dt = msgs[0].get_datetime(); bulletin.rep_year = dt.year; bulletin.rep_month = dt.month; bulletin.rep_day = dt.day; bulletin.rep_hour = dt.hour; bulletin.rep_minute = dt.minute; bulletin.rep_second = dt.second; bulletin.master_table_number = 0; bulletin.originating_centre = opts.centre != MISSING_INT ? opts.centre : 255; bulletin.originating_subcentre = opts.subcentre != MISSING_INT ? opts.subcentre : 255; bulletin.update_sequence_number = 0; if (BufrBulletin* b = dynamic_cast(&bulletin)) { // Take from opts b->edition_number = 4; b->master_table_version_number = 17; b->master_table_version_number_local = 0; b->compression = false; } if (CrexBulletin* b = dynamic_cast(&bulletin)) { // TODO: change using BUFR tables, when the encoder can encode the full // CREX ed.2 header b->edition_number = 2; b->master_table_version_number = 3; b->master_table_version_number_local = 0; b->master_table_version_number_bufr = 0; b->has_check_digit = false; } } void Template::to_subset(const Msg& msg, wreport::Subset& subset) { this->msg = &msg; this->subset = ⊂ this->c_station = msg.find_context(Level(), Trange()); this->c_gnd_instant = msg.find_context(Level(1), Trange::instant()); } void Template::add(Varcode code, const msg::Context* ctx, int shortcut) const { if (!ctx) subset->store_variable_undef(code); else if (const Var* var = ctx->find_by_id(shortcut)) subset->store_variable(code, *var); else subset->store_variable_undef(code); } void Template::add(Varcode code, const msg::Context* ctx, Varcode srccode) const { if (!ctx) subset->store_variable_undef(code); else if (const Var* var = ctx->find(srccode)) subset->store_variable(code, *var); else subset->store_variable_undef(code); } void Template::add(Varcode code, const msg::Context* ctx) const { if (!ctx) subset->store_variable_undef(code); else if (const Var* var = ctx->find(code)) subset->store_variable(*var); else subset->store_variable_undef(code); } void Template::add(Varcode code, int shortcut) const { add(code, msg->find_by_id(shortcut)); } void Template::add(Varcode code, Varcode srccode, const Level& level, const Trange& trange) const { add(code, msg->get(srccode, level, trange)); } void Template::add(wreport::Varcode code, const wreport::Var* var) const { if (var) subset->store_variable(code, *var); else subset->store_variable_undef(code); } const Var* Template::find_station_var(wreport::Varcode code) const { if (!c_station) return nullptr; return c_station->find(code); } void Template::do_station_name(wreport::Varcode dstcode) const { if (!c_station) subset->store_variable_undef(dstcode); else if (const wreport::Var* var = c_station->find_by_id(DBA_MSG_ST_NAME)) { Varinfo info = subset->tables->btable->query(dstcode); Var name(info); if (var->isset()) name.setc_truncate(var->enqc()); subset->store_variable(move(name)); } else subset->store_variable_undef(dstcode); } void Template::do_ecmwf_past_wtr() const { int hour = msg->get_datetime().hour == 0xff ? 0 : msg->get_datetime().hour; if (hour % 6 == 0) { add(WR_VAR(0, 20, 4), DBA_MSG_PAST_WTR1_6H); add(WR_VAR(0, 20, 5), DBA_MSG_PAST_WTR2_6H); } else { add(WR_VAR(0, 20, 4), DBA_MSG_PAST_WTR1_3H); add(WR_VAR(0, 20, 5), DBA_MSG_PAST_WTR2_3H); } } void Template::do_station_height() const { add(WR_VAR(0, 7, 30), c_station); add(WR_VAR(0, 7, 31), c_station); } void Template::do_D01001() const { add(WR_VAR(0, 1, 1), c_station, DBA_MSG_BLOCK); add(WR_VAR(0, 1, 2), c_station, DBA_MSG_STATION); } void Template::do_D01004() const { do_D01001(); do_station_name(WR_VAR(0, 1, 15)); add(WR_VAR(0, 2, 1), c_station, DBA_MSG_ST_TYPE); } void Template::do_D01011() const { // Year if (const Var* var = find_station_var(WR_VAR(0, 4, 1))) subset->store_variable(WR_VAR(0, 4, 1), *var); else if (!msg->get_datetime().is_missing()) subset->store_variable_i(WR_VAR(0, 4, 1), msg->get_datetime().year); else subset->store_variable_undef(WR_VAR(0, 4, 1)); // Month if (const Var* var = find_station_var(WR_VAR(0, 4, 2))) subset->store_variable(WR_VAR(0, 4, 2), *var); else if (!msg->get_datetime().is_missing()) subset->store_variable_i(WR_VAR(0, 4, 2), msg->get_datetime().month); else subset->store_variable_undef(WR_VAR(0, 4, 2)); // Day if (const Var* var = find_station_var(WR_VAR(0, 4, 3))) subset->store_variable(WR_VAR(0, 4, 3), *var); else if (!msg->get_datetime().is_missing()) subset->store_variable_i(WR_VAR(0, 4, 3), msg->get_datetime().day); else subset->store_variable_undef(WR_VAR(0, 4, 3)); } int Template::do_D01012() const { int res = MISSING_INT; // Hour if (const Var* var = find_station_var(WR_VAR(0, 4, 4))) { subset->store_variable(WR_VAR(0, 4, 4), *var); res = var->enqi(); } else if (!msg->get_datetime().is_missing()) { subset->store_variable_i(WR_VAR(0, 4, 4), msg->get_datetime().hour); res = msg->get_datetime().hour; } else subset->store_variable_undef(WR_VAR(0, 4, 4)); // Minute if (const Var* var = find_station_var(WR_VAR(0, 4, 5))) subset->store_variable(WR_VAR(0, 4, 5), *var); else if (!msg->get_datetime().is_missing()) subset->store_variable_i(WR_VAR(0, 4, 5), msg->get_datetime().minute); else subset->store_variable_undef(WR_VAR(0, 4, 5)); return res; } void Template::do_D01013() const { do_D01012(); // Second if (const Var* var = find_station_var(WR_VAR(0, 4, 6))) subset->store_variable(WR_VAR(0, 4, 6), *var); else if (!msg->get_datetime().is_missing()) subset->store_variable_i(WR_VAR(0, 4, 6), msg->get_datetime().second); else subset->store_variable_undef(WR_VAR(0, 4, 6)); } void Template::do_D01021() const { add(WR_VAR(0, 5, 1), c_station, DBA_MSG_LATITUDE); add(WR_VAR(0, 6, 1), c_station, DBA_MSG_LONGITUDE); } void Template::do_D01022() const { do_D01021(); add(WR_VAR(0, 7, 1), c_station, DBA_MSG_HEIGHT_STATION); } void Template::do_D01023() const { add(WR_VAR(0, 5, 2), c_station, DBA_MSG_LATITUDE); add(WR_VAR(0, 6, 2), c_station, DBA_MSG_LONGITUDE); } } } } dballe-7.7/dballe/msg/ltypes.txt0000644000175000017500000000510212652630043013624 000000000000000 Reserved 1 Ground or Water Surface 2 Cloud Base Level 3 Level of Cloud Tops 4 Level of 0C Isotherm 5 Level of Adiabatic Condensation Lifted from the Surface 6 Maximum Wind Level 7 Tropopause 8 Nominal Top of the Atmosphere DB-All.e encodes the channel number of polar satellites in L1 9 Sea Bottom 10-19 Reserved 20 Isothermal Level K/10 21-99 Reserved 100 Isobaric Surface Pa 101 Mean Sea Level 102 Specific Altitude Above Mean Sea Level mm 103 Specified Height Level Above Ground mm 104 Sigma Level 1/10000 105 Hybrid Level 106 Depth Below Land Surface mm 107 Isentropic (theta) Level K/10 108 Level at Specified Pressure Difference from Ground to Level Pa 109 Potential Vorticity Surface 10-9 K m2 kg-1 s-1 110 Reserved 111 Eta (NAM) Level (see note below) 1/10000 112 116 Reserved 117 Mixed Layer Depth mm 118-159 Reserved 160 Depth Below Sea Level mm 161-191 Reserved 200 Entire atmosphere (considered as a single layer) 201 Entire ocean (considered as a single layer) 204 Highest tropospheric freezing level 206 Grid scale cloud bottom level 207 Grid scale cloud top level 209 Boundary layer cloud bottom level 210 Boundary layer cloud top level 211 Boundary layer cloud layer 212 Low cloud bottom level 213 Low cloud top level 214 Low cloud layer 215 Cloud ceiling 220 Planetary Boundary Layer 222 Middle cloud bottom level 223 Middle cloud top level 224 Middle cloud layer 232 High cloud bottom level 233 High cloud top level 234 High cloud layer 235 Ocean Isotherm Level K/10 240 Ocean Mixed Layer 241 Ordered Sequence of Data 242 Convective cloud bottom level 243 Convective cloud top level 244 Convective cloud layer 245 Lowest level of the wet bulb zero 246 Maximum equivalent potential temperature level 247 Equilibrium level 248 Shallow convective cloud bottom level 249 Shallow convective cloud top level 251 Deep convective cloud bottom level 252 Deep convective cloud top level 253 Lowest bottom level of supercooled liquid water layer 254 Highest top level of supercooled liquid water layer 256 Clouds 257 Information about the station that generated the data 258 (use when ltype1=256) Cloud Data group, L2 = 1 low clouds, 2 middle clouds, 3 high clouds, 0 others 259 (use when ltype1=256) Individual cloud groups, L2 = group number 260 (use when ltype1=256) Cloud drift, L2 = group number 261 (use when ltype1=256) Cloud elevation, L2 = group number; (use when ltype1=264) L2 = swell wave group number 262 (use when ltype1=256) Direction and elevation of clouds, L2 is ignored 263 (use when ltype1=256) Cloud groups with bases below station level, L2 = group number 264 Waves dballe-7.7/dballe/msg/wr_codec-test.cc0000644000175000017500000000051712652630043014621 00000000000000#include "tests.h" #include "wr_codec.h" #include using namespace std; using namespace dballe; using namespace dballe::tests; namespace { class Tests : public TestCase { using TestCase::TestCase; void register_tests() override { add_method("empty", []() { }); } } test("msg_wr_codec"); } dballe-7.7/dballe/msg/mktranges0000755000175000017500000000632312652630043013472 00000000000000#!/usr/bin/perl -w my $op = $ARGV[0]; use strict; use warnings; my @descs = ( [ 0, q{Average} ], [ 1, q{Accumulation} ], [ 2, q{Maximum} ], [ 3, q{Minimum} ], [ 4, q{Difference (value at the end of the time range minus value at the beginning)} ], [ 5, q{Root Mean Square} ], [ 6, q{Standard Deviation} ], [ 7, q{Covariance (temporal variance)} ], [ 8, q{Difference (value at the beginning of the time range minus value at the end)} ], [ 9, q{Ratio} ], [ 51, q{Climatological Mean Value} ], [ '10-191', q{Reserved} ], [ '192-254', q{Reserved for Local Use} ], [ 200, q{Vectorial mean} ], [ 201, q{Mode} ], [ 202, q{Standard deviation vectorial mean} ], [ 203, q{Vectorial maximum} ], [ 204, q{Vectorial minimum} ], [ 205, q{Product with a valid time ranging inside the given period} ], [ 254, q{Istantaneous value} ], ); my @notes = ( q{Validity time is defined as the time at which the data are measured or at which forecast is valid; for statistically processed data, the validity time is the end of the time interval.}, q{Reference time is defined as the nominal time of an observation for observed values, or as the time at which a model forecast starts for forecast values.}, q{The date and time in DB-All.e are always the validity date and time of a value, regardless of the value being an observation or a forecast.}, q{P1 is defined as the difference in seconds between validity time and reference time. For forecasts it is the positive forecast time. For observed values, the reference time is usually the same as the validity time, therefore P1 is zero. However P1 < 0 is a valid case for reports containing data in the past with respect to the nominal report time.}, q{P2 is defined as the duration of the period over which statistical processing is performed, and is always nonnegative. Note that, for instantaneous values, P2 is always zero.}, # q{The Eta (NAM) vertical coordinate system involves normalizing the pressure at some point on a specific level by the mean sea level pressure at that point.}, ); if ($op eq 'dox') { print q{/**@defgroup trange_table Time range values @ingroup tables Definition of the main concepts related to the description of time range and statistical processing for observed and forecast data: }; for my $n (@notes) { $n =~ s/\n+/\n/g; print '\\li ', $n; } print q{ The following table lists the possible values for pindicator and the interpretation of the corresponding values of P1 and P2 specifying a time range: }; for my $d (@descs) { print '\\li \b ', $d->[0], " "; my $desc = $d->[1]; $desc =~ s/\n+/\n/g; print $desc; } print "*/\n"; } elsif ($op eq 'tex') { print q( Definition of the main concepts related to the description of time range and statistical processing for observed and forecast data: \\begin{itemize} ); for my $n (@notes) { print '\\item ', $n, "\n"; } print q(\\end{itemize} The following table lists the possible values for pindicator and the interpretation of the corresponding values of P1 and P2 specifying a time range: \\begin{description} ); for my $d (@descs) { print '\\item [', $d->[0], "]\n"; print $d->[1]; } print q(\\end{description} ); } else { print STDERR "Unknown operation: $op\n"; exit 1; } exit 0; dballe-7.7/dballe/msg/vars.h0000644000175000017500000001716512652630120012677 00000000000000#ifndef DBA_MSG_VARS_H #define DBA_MSG_VARS_H /** @file * @ingroup msg * Shortcut IDs and functions to quickly refer to commonly used values inside a * ::dba_msg. * * The shortcuts are defined in the file vars.csv, which maps a name to the tuple * (preferred C type, BLocal, Level type, L1, L2, P indicator, P1, P2). The file * vars.csv is used to generate code (vars.h and vars.c) that provides a set of * getters and setters for every named value. */ #include namespace dballe { /** * Full data corresponding to a shortcut ID */ struct MsgVarShortcut { /** Variable description code */ wreport::Varcode code; /** Type of the first level. See @ref level_table. */ int ltype1; /** L1 value of the level. See @ref level_table. */ int l1; /** Type of the second level. See @ref level_table. */ int ltype2; /** L2 value of the level. See @ref level_table. */ int l2; /** Time range type indicator. See @ref trange_table. */ int pind; /** Time range P1 indicator. See @ref trange_table. */ int p1; /** Time range P2 indicator. See @ref trange_table. */ int p2; }; /** Array with all the full expansions of the shortcut IDs, indexed by shortcut * ID */ extern struct MsgVarShortcut shortcutTable[]; /** Resolve a var name to a var ID */ int resolve_var(const char* name); /** Resolve a var name to a var ID, avoiding to compute the length of name */ int resolve_var_substring(const char* name, int len); /** WMO block number */ #define DBA_MSG_BLOCK 0 /** WMO station number */ #define DBA_MSG_STATION 1 /** Aircraft registration number or other identification */ #define DBA_MSG_FLIGHT_REG_NO 2 /** Mobile station identifier */ #define DBA_MSG_IDENT 3 /** Station or site name */ #define DBA_MSG_ST_NAME 4 /** ICAO location indicator */ #define DBA_MSG_ST_NAME_ICAO 5 /** Report mnemonic */ #define DBA_MSG_REP_MEMO 6 /** Air quality observing station local code */ #define DBA_MSG_POLL_LCODE 7 /** Airbase air quality observing station code */ #define DBA_MSG_POLL_SCODE 8 /** GEMS air quality observing station code */ #define DBA_MSG_POLL_GEMSCODE 9 /** Air quality observing station dominant emission source */ #define DBA_MSG_POLL_SOURCE 10 /** Air quality observing station area type */ #define DBA_MSG_POLL_ATYPE 11 /** Air quality observing station terrain type */ #define DBA_MSG_POLL_TTYPE 12 /** Type of station */ #define DBA_MSG_ST_TYPE 13 /** Type of instrumentation for wind measurement */ #define DBA_MSG_WIND_INST 14 /** Precision of temperature observation */ #define DBA_MSG_TEMP_PRECISION 15 /** Aircraft navigational system */ #define DBA_MSG_NAVSYS 16 /** Aircraft data relay system */ #define DBA_MSG_DATA_RELAY 17 /** Aircraft roll angle */ #define DBA_MSG_FLIGHT_ROLL 18 /** Original specification of latitude/longitude */ #define DBA_MSG_LATLON_SPEC 19 /** Year of the observation */ #define DBA_MSG_YEAR 20 /** Month of the observation */ #define DBA_MSG_MONTH 21 /** Day of the observation */ #define DBA_MSG_DAY 22 /** Hour of the observation */ #define DBA_MSG_HOUR 23 /** Minute of the observation */ #define DBA_MSG_MINUTE 24 /** Second of the observation */ #define DBA_MSG_SECOND 25 /** Latitude of the station */ #define DBA_MSG_LATITUDE 26 /** Longiture of the station */ #define DBA_MSG_LONGITUDE 27 /** Isobaric surface */ #define DBA_MSG_ISOBARIC_SURFACE 28 /** Height of release of sonde above msl */ #define DBA_MSG_HEIGHT_RELEASE 29 /** Height of station */ #define DBA_MSG_HEIGHT_STATION 30 /** Height of barometer above mean sea level */ #define DBA_MSG_HEIGHT_BARO 31 /** Phase of aircraft flight */ #define DBA_MSG_FLIGHT_PHASE 32 /** Time significance */ #define DBA_MSG_TIMESIG 33 /** Station elevation quality mark (for mobile stations) */ #define DBA_MSG_STATION_HEIGHT_QUALITY 34 /** Total cloud cover (N) */ #define DBA_MSG_CLOUD_N 35 /** Cloud amount (N4) */ #define DBA_MSG_CLOUD_N4 36 /** Cloud amount (C4) */ #define DBA_MSG_CLOUD_C4 37 /** Height of base of cloud (H4) */ #define DBA_MSG_CLOUD_H4 38 /** Cloud amount (N3) */ #define DBA_MSG_CLOUD_N3 39 /** Cloud amount (C3) */ #define DBA_MSG_CLOUD_C3 40 /** Height of base of cloud (H3) */ #define DBA_MSG_CLOUD_H3 41 /** Cloud amount (N2) */ #define DBA_MSG_CLOUD_N2 42 /** Cloud amount (C2) */ #define DBA_MSG_CLOUD_C2 43 /** Height of base of cloud (H2) */ #define DBA_MSG_CLOUD_H2 44 /** Cloud amount (N1) */ #define DBA_MSG_CLOUD_N1 45 /** Cloud amount (C1) */ #define DBA_MSG_CLOUD_C1 46 /** Height of base of cloud (H1) */ #define DBA_MSG_CLOUD_H1 47 /** Cloud type (CH) */ #define DBA_MSG_CLOUD_CH 48 /** Cloud type (CM) */ #define DBA_MSG_CLOUD_CM 49 /** Cloud type (CL) */ #define DBA_MSG_CLOUD_CL 50 /** Cloud amount (NH) */ #define DBA_MSG_CLOUD_NH 51 /** Height of base of cloud (HH) */ #define DBA_MSG_CLOUD_HH 52 /** Wind direction at 10 metres above ground */ #define DBA_MSG_WIND_DIR 53 /** Wind speed at 10 metres above ground */ #define DBA_MSG_WIND_SPEED 54 /** Extreme counterclockwise wind direction of a variable wind at 10 metres above ground */ #define DBA_MSG_EX_CCW_WIND 55 /** Extreme clockwise wind direction of a variable wind at 10 metres above ground */ #define DBA_MSG_EX_CW_WIND 56 /** Maximum wind gust speed at 10 metres above ground */ #define DBA_MSG_WIND_GUST_MAX_SPEED 57 /** Maximum wind gust direction at 10 metres above ground */ #define DBA_MSG_WIND_GUST_MAX_DIR 58 /** Altimeter setting (QNH) */ #define DBA_MSG_QNH 59 /** Temperature at 2 metres above ground */ #define DBA_MSG_TEMP_2M 60 /** Wet bulb temperature at 2 metres above ground */ #define DBA_MSG_WET_TEMP_2M 61 /** Dew point at 2 metres above ground */ #define DBA_MSG_DEWPOINT_2M 62 /** Humidity at 2 metres above ground */ #define DBA_MSG_HUMIDITY 63 /** Pressure reduced to mean sea level */ #define DBA_MSG_PRESS_MSL 64 /** Direction of motion of moving observing platform */ #define DBA_MSG_ST_DIR 65 /** Speed of motion of moving observing platform */ #define DBA_MSG_ST_SPEED 66 /** Type of measuring equipment used */ #define DBA_MSG_MEAS_EQUIP_TYPE 67 /** Radiosonde type */ #define DBA_MSG_SONDE_TYPE 68 /** Radiosonde computational method */ #define DBA_MSG_SONDE_METHOD 69 /** Solar and infrared radiation correction */ #define DBA_MSG_SONDE_CORRECTION 70 /** Tracking technique/status of system used */ #define DBA_MSG_SONDE_TRACKING 71 /** Pressure at ground level */ #define DBA_MSG_PRESS 72 /** Anemometer height */ #define DBA_MSG_HEIGHT_ANEM 73 /** Total show depth */ #define DBA_MSG_TOT_SNOW 74 /** Visibility */ #define DBA_MSG_VISIBILITY 75 /** Present weather */ #define DBA_MSG_PRES_WTR 76 /** General weather indicator (TAF/METAR) */ #define DBA_MSG_METAR_WTR 77 /** State of ground (with or without snow) */ #define DBA_MSG_STATE_GROUND 78 /** Sea/water surface temperature */ #define DBA_MSG_WATER_TEMP 79 /** Past weather (1 - 6h) */ #define DBA_MSG_PAST_WTR1_6H 80 /** Past weather (2 - 6h) */ #define DBA_MSG_PAST_WTR2_6H 81 /** Characteristic of pressure tendency */ #define DBA_MSG_PRESS_TEND 82 /** Past weather (1 - 3h) */ #define DBA_MSG_PAST_WTR1_3H 83 /** Past weather (2 - 3h) */ #define DBA_MSG_PAST_WTR2_3H 84 /** 24 hour pressure change at ground level */ #define DBA_MSG_PRESS_24H 85 /** 3 hour pressure change at ground level */ #define DBA_MSG_PRESS_3H 86 /** Total precipitation in the last 24 hours */ #define DBA_MSG_TOT_PREC24 87 /** Total precipitation in the last 12 hours */ #define DBA_MSG_TOT_PREC12 88 /** Total precipitation in the last 6 hours */ #define DBA_MSG_TOT_PREC6 89 /** Total precipitation in the last 3 hours */ #define DBA_MSG_TOT_PREC3 90 /** Total precipitation in the last hour */ #define DBA_MSG_TOT_PREC1 91 /** Number of items in dba_msg_vartable */ #define DBA_MSG_VARTABLE_SIZE 91 } #endif dballe-7.7/dballe/msg/vars.cc0000644000175000017500000004423312652630120013031 00000000000000/* C++ code produced by gperf version 3.0.4 */ /* Command-line: gperf */ /* Computed positions: -k'1,6-7,9,11,$' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif #include #include #include namespace dballe { struct msgvardef { const char* name; int var; }; #define TOTAL_KEYWORDS 92 #define MIN_WORD_LENGTH 3 #define MAX_WORD_LENGTH 22 #define MIN_HASH_VALUE 5 #define MAX_HASH_VALUE 287 /* maximum key range = 283, duplicates = 0 */ class MsgVarLookup { private: static inline unsigned int hash (const char *str, unsigned int len); public: static struct msgvardef *find (const char *str, unsigned int len); }; inline unsigned int MsgVarLookup::hash (register const char *str, register unsigned int len) { static unsigned short asso_values[] = { 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 75, 60, 40, 125, 288, 20, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 5, 288, 15, 0, 10, 25, 5, 55, 5, 5, 60, 288, 5, 45, 15, 0, 85, 0, 0, 5, 0, 0, 40, 0, 40, 288, 115, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288 }; register int hval = len; switch (hval) { default: hval += asso_values[(unsigned char)str[10]]; /*FALLTHROUGH*/ case 10: case 9: hval += asso_values[(unsigned char)str[8]]; /*FALLTHROUGH*/ case 8: case 7: hval += asso_values[(unsigned char)str[6]]; /*FALLTHROUGH*/ case 6: hval += asso_values[(unsigned char)str[5]]; /*FALLTHROUGH*/ case 5: case 4: case 3: case 2: case 1: hval += asso_values[(unsigned char)str[0]]; break; } return hval + asso_values[(unsigned char)str[len - 1]]; } static struct msgvardef wordlist[] = { {""}, {""}, {""}, {""}, {""}, {"press", DBA_MSG_PRESS}, {"navsys", DBA_MSG_NAVSYS}, {""}, {"qnh", DBA_MSG_QNH}, {""}, {"block", DBA_MSG_BLOCK}, {""}, {""}, {""}, {"hour", DBA_MSG_HOUR}, {"poll_ttype", DBA_MSG_POLL_TTYPE}, {"st_dir", DBA_MSG_ST_DIR}, {"st_type", DBA_MSG_ST_TYPE}, {""}, {""}, {"sonde_type", DBA_MSG_SONDE_TYPE}, {""}, {"cloud_n", DBA_MSG_CLOUD_N}, {""}, {"height_station", DBA_MSG_HEIGHT_STATION}, {"month", DBA_MSG_MONTH}, {""}, {""}, {"cloud_nh", DBA_MSG_CLOUD_NH}, {"temp_precision", DBA_MSG_TEMP_PRECISION}, {"poll_atype", DBA_MSG_POLL_ATYPE}, {"minute", DBA_MSG_MINUTE}, {"st_name", DBA_MSG_ST_NAME}, {"cloud_hh", DBA_MSG_CLOUD_HH}, {""}, {""}, {""}, {""}, {"cloud_ch", DBA_MSG_CLOUD_CH}, {"height_release", DBA_MSG_HEIGHT_RELEASE}, {"press_tend", DBA_MSG_PRESS_TEND}, {"sonde_correction", DBA_MSG_SONDE_CORRECTION}, {""}, {"st_speed", DBA_MSG_ST_SPEED}, {"sonde_tracking", DBA_MSG_SONDE_TRACKING}, {""}, {""}, {""}, {"cloud_cm", DBA_MSG_CLOUD_CM}, {""}, {"poll_scode", DBA_MSG_POLL_SCODE}, {"height_anem", DBA_MSG_HEIGHT_ANEM}, {""}, {"pres_wtr", DBA_MSG_PRES_WTR}, {""}, {""}, {"second", DBA_MSG_SECOND}, {""}, {"press_3h", DBA_MSG_PRESS_3H}, {"tot_prec6", DBA_MSG_TOT_PREC6}, {""}, {""}, {""}, {"cloud_n3", DBA_MSG_CLOUD_N3}, {""}, {"ident", DBA_MSG_IDENT}, {""}, {""}, {"cloud_h3", DBA_MSG_CLOUD_H3}, {""}, {"water_temp", DBA_MSG_WATER_TEMP}, {""}, {""}, {"cloud_c3", DBA_MSG_CLOUD_C3}, {""}, {""}, {""}, {"timesig", DBA_MSG_TIMESIG}, {"cloud_cl", DBA_MSG_CLOUD_CL}, {"metar_wtr", DBA_MSG_METAR_WTR}, {"wind_speed", DBA_MSG_WIND_SPEED}, {"latlon_spec", DBA_MSG_LATLON_SPEC}, {"flight_phase", DBA_MSG_FLIGHT_PHASE}, {"cloud_n2", DBA_MSG_CLOUD_N2}, {"press_24h", DBA_MSG_PRESS_24H}, {"ex_cw_wind", DBA_MSG_EX_CW_WIND}, {""}, {""}, {"cloud_h2", DBA_MSG_CLOUD_H2}, {""}, {""}, {""}, {"station", DBA_MSG_STATION}, {"cloud_c2", DBA_MSG_CLOUD_C2}, {""}, {"poll_lcode", DBA_MSG_POLL_LCODE}, {""}, {"temp_2m", DBA_MSG_TEMP_2M}, {"cloud_n1", DBA_MSG_CLOUD_N1}, {"tot_prec3", DBA_MSG_TOT_PREC3}, {""}, {""}, {""}, {"cloud_h1", DBA_MSG_CLOUD_H1}, {"longitude", DBA_MSG_LONGITUDE}, {"meas_equip_type", DBA_MSG_MEAS_EQUIP_TYPE}, {"wet_temp_2m", DBA_MSG_WET_TEMP_2M}, {""}, {"cloud_c1", DBA_MSG_CLOUD_C1}, {"wind_inst", DBA_MSG_WIND_INST}, {""}, {"poll_source", DBA_MSG_POLL_SOURCE}, {""}, {"poll_gemscode", DBA_MSG_POLL_GEMSCODE}, {""}, {""}, {""}, {""}, {"rep_memo", DBA_MSG_REP_MEMO}, {"press_msl", DBA_MSG_PRESS_MSL}, {""}, {""}, {"wind_gust_max_dir", DBA_MSG_WIND_GUST_MAX_DIR}, {"latitude", DBA_MSG_LATITUDE}, {"year", DBA_MSG_YEAR}, {""}, {""}, {""}, {""}, {""}, {""}, {"dewpoint_2m", DBA_MSG_DEWPOINT_2M}, {"state_ground", DBA_MSG_STATE_GROUND}, {"tot_snow", DBA_MSG_TOT_SNOW}, {""}, {""}, {""}, {"past_wtr2_6h", DBA_MSG_PAST_WTR2_6H}, {"wind_dir", DBA_MSG_WIND_DIR}, {""}, {""}, {""}, {"sonde_method", DBA_MSG_SONDE_METHOD}, {"day", DBA_MSG_DAY}, {"wind_gust_max_speed", DBA_MSG_WIND_GUST_MAX_SPEED}, {""}, {""}, {""}, {"cloud_n4", DBA_MSG_CLOUD_N4}, {""}, {""}, {""}, {"past_wtr1_6h", DBA_MSG_PAST_WTR1_6H}, {"cloud_h4", DBA_MSG_CLOUD_H4}, {""}, {"tot_prec12", DBA_MSG_TOT_PREC12}, {""}, {"past_wtr2_3h", DBA_MSG_PAST_WTR2_3H}, {"cloud_c4", DBA_MSG_CLOUD_C4}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"flight_reg_no", DBA_MSG_FLIGHT_REG_NO}, {"tot_prec1", DBA_MSG_TOT_PREC1}, {""}, {"ex_ccw_wind", DBA_MSG_EX_CCW_WIND}, {"past_wtr1_3h", DBA_MSG_PAST_WTR1_3H}, {""}, {""}, {"data_relay", DBA_MSG_DATA_RELAY}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"humidity", DBA_MSG_HUMIDITY}, {""}, {""}, {"isobaric_surface", DBA_MSG_ISOBARIC_SURFACE}, {"st_name_icao", DBA_MSG_ST_NAME_ICAO}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"tot_prec24", DBA_MSG_TOT_PREC24}, {"height_baro", DBA_MSG_HEIGHT_BARO}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"visibility", DBA_MSG_VISIBILITY}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"flight_roll", DBA_MSG_FLIGHT_ROLL}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"station_height_quality", DBA_MSG_STATION_HEIGHT_QUALITY} }; struct msgvardef * MsgVarLookup::find (register const char *str, register unsigned int len) { if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len); if (key <= MAX_HASH_VALUE && key >= 0) { register const char *s = wordlist[key].name; if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') return &wordlist[key]; } } return 0; } int resolve_var(const char* name) { struct msgvardef* res = MsgVarLookup::find(name, strlen(name)); if (res == NULL) return -1; else return res->var; } int resolve_var_substring(const char* name, int len) { struct msgvardef* res = MsgVarLookup::find(name, len); if (res == NULL) return -1; else return res->var; } struct MsgVarShortcut shortcutTable[] = { { WR_VAR(0, 1, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 2), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 8), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 11), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 19), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 63), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 194), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 212), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 213), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 214), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 215), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 216), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 217), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 2), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 5), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 61), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 62), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 63), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 70), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 2), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 3), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 4), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 5), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 6), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 5, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 6, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 7, 4), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 7, 7), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 7, 30), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 7, 31), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 8, 4), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 8, 21), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 33, 24), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 20, 10), 256, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 259, 4, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 259, 4, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 259, 4, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 259, 3, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 259, 3, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 259, 3, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 259, 2, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 259, 2, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 259, 2, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 259, 1, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 259, 1, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 259, 1, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 258, 3, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 258, 2, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 258, 1, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 258, 0, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 258, 0, 254, 0, 0 }, { WR_VAR(0, 11, 1), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 2), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 16), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 17), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 41), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 43), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 10, 52), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 12, 101), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 12, 102), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 12, 103), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 13, 3), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 10, 51), 101, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 1, 12), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 1, 13), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 3), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 12), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 13), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 14), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 10, 4), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 10, 197), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 13, 13), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 1), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 3), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 9), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 62), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 22, 43), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 4), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 21600 }, { WR_VAR(0, 20, 5), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 21600 }, { WR_VAR(0, 10, 63), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 10800 }, { WR_VAR(0, 20, 4), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 10800 }, { WR_VAR(0, 20, 5), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 10800 }, { WR_VAR(0, 10, 60), 1, MISSING_INT, MISSING_INT, MISSING_INT, 4, 0, 86400 }, { WR_VAR(0, 10, 60), 1, MISSING_INT, MISSING_INT, MISSING_INT, 4, 0, 10800 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 86400 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 43200 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 21600 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 10800 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 3600 }, }; } // namespace dballe dballe-7.7/dballe/msg/context.cc0000644000175000017500000001672612652630043013554 00000000000000/* * msg/context - Hold variables with the same physical context * * Copyright (C) 2005--2011 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include #include #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace msg { Context::Context(const Level& lev, const Trange& tr) : level(lev), trange(tr) { } Context::Context(const Context& c) : level(c.level), trange(c.trange) { // Reserve space for the new vars data.reserve(c.data.size()); // Copy the variables for (vector::const_iterator i = c.data.begin(); i != c.data.end(); ++i) data.push_back(new Var(**i)); } Context::~Context() { for (vector::iterator i = data.begin(); i != data.end(); ++i) delete *i; } Context& Context::operator=(const Context& src) { // Manage a = a if (this == &src) return *this; level = src.level; trange = src.trange; // Delete existing vars for (vector::iterator i = data.begin(); i != data.end(); ++i) delete *i; data.clear(); // Reserve space for the new vars data.reserve(src.data.size()); // Copy the variables for (vector::const_iterator i = src.data.begin(); i != src.data.end(); ++i) data.push_back(new Var(**i)); return *this; } bool Context::is_station() const { return level == Level() && trange == Trange(); } int Context::compare(const Context& ctx) const { int res; if ((res = level.compare(ctx.level))) return res; return trange.compare(ctx.trange); } int Context::compare(const Level& lev, const Trange& tr) const { int res; if ((res = level.compare(lev))) return res; return trange.compare(tr); } void Context::set(const Var& var) { set(unique_ptr(new Var(var))); } void Context::seti(wreport::Varcode code, int val) { set(newvar(code, val)); } void Context::setd(wreport::Varcode code, double val) { set(newvar(code, val)); } void Context::setc(wreport::Varcode code, const char* val) { set(newvar(code, val)); } void Context::set(unique_ptr var) { Varcode code = var->code(); int idx = find_index(code); if (idx != -1) { /* Replace the variable */ delete data[idx]; } else { /* Add the value */ /* Enlarge the buffer */ data.resize(data.size() + 1); /* Insertionsort. Crude, but our datasets should be too small for an * RB-Tree to be worth */ for (idx = data.size() - 1; idx > 0; --idx) if (data[idx - 1]->code() > code) data[idx] = data[idx - 1]; else break; } data[idx] = var.release(); } int Context::find_index(Varcode code) const { /* Binary search */ int low = 0, high = data.size() - 1; while (low <= high) { int middle = low + (high - low)/2; int cmp = (int)code - (int)data[middle]->code(); if (cmp < 0) high = middle - 1; else if (cmp > 0) low = middle + 1; else return middle; } return -1; } const Var* Context::find(Varcode code) const { int idx = find_index(code); return (idx == -1) ? NULL : data[idx]; } Var* Context::edit(Varcode code) { int idx = find_index(code); return (idx == -1) ? NULL : data[idx]; } bool Context::remove(Varcode code) { int idx = find_index(code); if (idx == -1) return false; Var* res = data[idx]; data.erase(data.begin() + idx); delete res; return true; } const Var* Context::find_by_id(int id) const { return find(shortcutTable[id].code); } void Context::print(FILE* out) const { stringstream header; header << "Level " << level << " tr " << trange; fprintf(out, "%s ", header.str().c_str()); if (data.size() > 0) { fprintf(out, " %zd vars:\n", data.size()); for (vector::const_iterator i = data.begin(); i != data.end(); ++i) (*i)->print(out); } else fprintf(out, "exists but is empty.\n"); } static void context_summary(const msg::Context& c, ostream& out) { out << "c(" << c.level << ", " << c.trange << ")"; } static void var_summary(const Var& var, ostream& out) { out << varcode_format(var.code()) << "[" << var.info()->desc << "]"; } static void context_var_summary(const msg::Context& c, const Var& var, ostream& out) { out << "Variable "; context_summary(c, out); out << " "; var_summary(var, out); } unsigned Context::diff(const Context& ctx) const { if (level != ctx.level || trange != ctx.trange) { notes::log() << "the contexts are different (first is " << level << ", " << trange << " second is " << ctx.level << ", " << ctx.trange << ")" << endl; return 1; } size_t i1 = 0, i2 = 0; unsigned diffs = 0; while (i1 < data.size() || i2 < ctx.data.size()) { if (i1 == data.size()) { context_var_summary(ctx, *ctx.data[i2], notes::log()); notes::log() << " exists only in the second message" << endl; ++i2; ++diffs; } else if (i2 == ctx.data.size()) { context_var_summary(*this, *data[i1], notes::log()); notes::log() << " exists only in the first message" << endl; ++i1; ++diffs; } else { int cmp = (int)data[i1]->code() - (int)ctx.data[i2]->code(); if (cmp == 0) { diffs += data[i1]->diff(*ctx.data[i2]); ++i1; ++i2; } else if (cmp < 0) { if (data[i1]->isset()) { context_var_summary(*this, *data[i1], notes::log()); notes::log() << " exists only in the first message" << endl; ++diffs; } ++i1; } else { if (ctx.data[i2]->isset()) { context_var_summary(ctx, *ctx.data[i2], notes::log()); notes::log() << " exists only in the second message" << endl; ++diffs; } ++i2; } } } return diffs; } const Var* Context::find_vsig() const { // Check if we have the right context information if ((level.ltype1 != 100 && level.ltype1 != 102 && level.ltype1 != 103) || trange != Trange::instant()) return NULL; // Look for VSS variable const Var* res = find(WR_VAR(0, 8, 42)); if (res == NULL) return NULL; // Ensure it is not undefined if (!res->isset()) return NULL; // Finally return it return res; } } } dballe-7.7/dballe/msg/wr_importers/0000755000175000017500000000000012653425050014362 500000000000000dballe-7.7/dballe/msg/wr_importers/temp.cc0000644000175000017500000004712412652630043015565 00000000000000/* * Copyright (C) 2005--2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "base.h" #include #include #include #include #include #include #include // Define to debug the sounding group matching algorithm // #define DEBUG_GROUPS #ifdef DEBUG_GROUPS #define debug_groups(...) fprintf(stderr, "grpmatch:" __VA_ARGS__) #else #define debug_groups(...) do {} while(0) #endif using namespace wreport; using namespace std; #define MISSING_PRESS -1.0 namespace dballe { namespace msg { namespace wr { class TempImporter : public WMOImporter { protected: double press; const Var* press_var; double surface_press; const Var* surface_press_var; void import_var(const Var& var); /** * If we identify sounding groups, this function can perform more accurate * sounding group import */ void import_group(unsigned start, unsigned length); public: TempImporter(const msg::Importer::Options& opts) : WMOImporter(opts) {} virtual ~TempImporter() {} virtual void init() { WMOImporter::init(); press = MISSING_PRESS; press_var = NULL; surface_press = MISSING_PRESS; surface_press_var = NULL; } /// Return true if \a code can be found at the start of a sounding group bool is_possible_group_var(Varcode code) { return WR_VAR_F(code) == 0 && WR_VAR_X(code) != 31 && WR_VAR_X(code) != 1; } /// If the next variables in the current subset look like \a group_count /// sounding groups, scan them and return true; otherwise return false. bool try_soundings(unsigned group_count) { // Check if the first var in the first candidate group is a likely start // of a sounding group if (pos + 1 == subset->size()) return false; const Var& start_var = (*subset)[pos + 1]; if (not is_possible_group_var(start_var.code())) return false; // start_var marks the start of a sounding group debug_groups("Candidate start var: %d (%01d%02d%03d) with group count %u\n", pos + 1, WR_VAR_F(start_var.code()), WR_VAR_X(start_var.code()), WR_VAR_Y(start_var.code()), group_count); // Seek forward until the same variable is found again, to compute the // group length unsigned group_length = 0; unsigned start = pos + 1; unsigned cur = start + 1; for ( ; cur < subset->size(); ++cur) { const Var& next = (*subset)[cur]; if (next.code() == start_var.code() || !is_possible_group_var(next.code())) { group_length = cur - start; if (start + group_count * group_length > subset->size()) return false; break; } } if (cur == subset->size()) group_length = cur-start; // Validate group_length checking that all groups start with start_var for (unsigned i = 0; i < group_count; ++i) { const Var& next = (*subset)[pos + 1 + i * group_length]; if (next.code() != start_var.code() && !is_possible_group_var(next.code())) { debug_groups(" Group count %u/%u fails check at leading var %01d%02d%03d\n", i, group_count, WR_VAR_F(next.code()), WR_VAR_X(next.code()), WR_VAR_Y(next.code())); return false; } } debug_groups("Validated first group: %d+%d\n", start, group_length); // Now we know how many groups there are and how long they are: iterate // them importing one at a time for (unsigned i = 0; i < group_count; ++i) import_group(pos + 1 + i * group_length, group_length); pos += 1 + group_count * group_length; return true; } virtual void run() { for (pos = 0; pos < subset->size(); ) { const Var& var = (*subset)[pos]; if (WR_VAR_F(var.code()) != 0 || !var.isset()) { // Ignore non-B variables and variables that are unset ++pos; } else if ((var.code() == WR_VAR(0, 31, 1) || var.code() == WR_VAR(0, 31, 2))) { // delayed descriptor replication count // Try to see if this is a sounding block, and import it a group // at a time if (!try_soundings(var.enqi())) // If it does not look like a sounding, ignore delayed // repetition count and proceed normally ++pos; } else { // Import all non-sounding vars import_var(var); ++pos; } } /* Extract surface data from the surface level */ if (surface_press != -1) { // Pressure is taken from a saved variable referencing to the original // pressure data in the message, to preserve data attributes if (surface_press_var && surface_press_var->isset() && msg->get_press_var()) msg->set_press_var(*surface_press_var); const Context* sfc = msg->find_context(Level(100, surface_press), Trange::instant()); if (sfc != NULL) { const Var* var = sfc->find(WR_VAR(0, 12, 1)); if (var && msg->get_temp_2m_var()) msg->set_temp_2m_var(*var); var = sfc->find(WR_VAR(0, 12, 3)); if (var && msg->get_dewpoint_2m_var()) msg->set_dewpoint_2m_var(*var); var = sfc->find(WR_VAR(0, 11, 1)); if (var && !msg->get_wind_dir_var()) msg->set_wind_dir_var(*var); var = sfc->find(WR_VAR(0, 11, 2)); if (var && !msg->get_wind_speed_var()) msg->set_wind_speed_var(*var); } } } MsgType scanType(const Bulletin& bulletin) const { switch (bulletin.data_category) { case 2: switch (bulletin.data_subcategory) { case 1: // 001 for PILOT data, case 2: // 002 for PILOT SHIP data, case 3: // 003 for PILOT MOBIL data. return MSG_PILOT; case 4: return MSG_TEMP; case 5: return MSG_TEMP_SHIP; case 255: switch (bulletin.data_subcategory_local) { case 0: { /* Guess looking at the variables */ if (bulletin.subsets.empty()) throw error_consistency("trying to import a TEMP message with no data subset"); const Subset& subset = bulletin.subsets[0]; if (subset.size() > 1 && subset[0].code() == WR_VAR(0, 1, 11)) return MSG_TEMP_SHIP; else return MSG_TEMP; } case 101: return MSG_TEMP; case 102: return MSG_TEMP_SHIP; case 91: case 92: return MSG_PILOT; } } break; case 6: return MSG_TEMP; } return MSG_TEMP; } }; std::unique_ptr Importer::createTemp(const msg::Importer::Options& opts) { return unique_ptr(new TempImporter(opts)); } void TempImporter::import_var(const Var& var) { switch (var.code()) { /* Identification of launch site and instrumentation */ case WR_VAR(0, 2, 3): msg->set_meas_equip_type_var(var); break; case WR_VAR(0, 2, 11): msg->set_sonde_type_var(var); break; case WR_VAR(0, 2, 12): msg->set_sonde_method_var(var); break; case WR_VAR(0, 2, 13): msg->set_sonde_correction_var(var); break; case WR_VAR(0, 2, 14): msg->set_sonde_tracking_var(var); break; /* Date/time of launch */ case WR_VAR(0, 8, 21): if (var.enqi() != 18) dba_verbose(DBA_VERB_BUFREX_MSG, "TEMP time significance is %d instead of 18", var.enqi()); break; /* Horizontal and vertical coordinates of launch site */ case WR_VAR(0, 7, 1): case WR_VAR(0, 7, 30): msg->set_height_station_var(var); break; case WR_VAR(0, 7, 31): msg->set_height_baro_var(var); break; case WR_VAR(0, 7, 7): msg->set_height_release_var(var); break; case WR_VAR(0, 33, 24): msg->set_station_height_quality_var(var); break; /* Cloud information reported with vertical soundings */ case WR_VAR(0, 8, 2): msg->set(var, WR_VAR(0, 8, 2), Level::cloud(258, 0), Trange::instant()); break; case WR_VAR(0, 20, 10): msg->set_cloud_n_var(var); break; case WR_VAR(0, 20, 11): msg->set_cloud_nh_var(var); break; case WR_VAR(0, 20, 13): msg->set_cloud_hh_var(var); break; case WR_VAR(0, 20, 12): { // CH CL CM int l2 = 1; if (pos > 0 && (*subset)[pos - 1].code() == WR_VAR(0, 20, 12)) { ++l2; if (pos > 1 && (*subset)[pos - 2].code() == WR_VAR(0, 20, 12)) ++l2; } msg->set(var, WR_VAR(0, 20, 12), Level::cloud(258, l2), Trange::instant()); break; } case WR_VAR(0, 22, 43): msg->set_water_temp_var(var); break; /* Temperature, dew-point and wind data at pressure levels */ // Long time period or displacement (since launch time) case WR_VAR(0, 4, 16): case WR_VAR(0, 4, 86): msg->set(var, WR_VAR(0, 4, 86), Level(100, press), Trange::instant()); break; // Extended vertical sounding significance case WR_VAR(0, 8, 42): { if (pos == subset->size() - 1) throw error_consistency("B08042 found at end of message"); if ((*subset)[pos + 1].code() == WR_VAR(0, 7, 4)) { // Pressure is reported later, we need to look ahead to compute the right level press_var = &((*subset)[pos + 1]); if (press_var->isset()) press = press_var->enqd(); else press = MISSING_INT; } msg->set(var, WR_VAR(0, 8, 42), Level(100, press), Trange::instant()); break; } // Pressure case WR_VAR(0, 7, 4): press = var.enqd(); press_var = &var; msg->set(var, WR_VAR(0, 10, 4), Level(100, press), Trange::instant()); break; // Vertical sounding significance case WR_VAR(0, 8, 1): { // This account for weird data that has '1' for VSS unsigned val = convert_BUFR08001_to_BUFR08042(var.enqi()); if (val != BUFR08042::ALL_MISSING) { unique_ptr nvar(newvar(WR_VAR(0, 8, 42), (int)val)); nvar->setattrs(var); msg->set(move(nvar), Level(100, press), Trange::instant()); } } if (var.enqi() & BUFR08001::SURFACE) { surface_press = press; surface_press_var = press_var; } break; // Geopotential case WR_VAR(0, 10, 3): msg->set(var, WR_VAR(0, 10, 8), Level(100, press), Trange::instant()); break; case WR_VAR(0, 10, 8): msg->set(var, WR_VAR(0, 10, 8), Level(100, press), Trange::instant()); break; case WR_VAR(0, 10, 9): msg->set(var, WR_VAR(0, 10, 8), Level(100, press), Trange::instant()); break; // Latitude displacement case WR_VAR(0, 5, 15): msg->set(var, WR_VAR(0, 5, 15), Level(100, press), Trange::instant()); break; // Longitude displacement case WR_VAR(0, 6, 15): msg->set(var, WR_VAR(0, 6, 15), Level(100, press), Trange::instant()); break; // Dry bulb temperature case WR_VAR(0, 12, 1): msg->set(var, WR_VAR(0, 12, 101), Level(100, press), Trange::instant()); break; case WR_VAR(0, 12, 101): msg->set(var, WR_VAR(0, 12, 101), Level(100, press), Trange::instant()); break; // Wet bulb temperature case WR_VAR(0, 12, 2): msg->set(var, WR_VAR(0, 12, 2), Level(100, press), Trange::instant()); break; // Dew point temperature case WR_VAR(0, 12, 3): msg->set(var, WR_VAR(0, 12, 103), Level(100, press), Trange::instant()); break; case WR_VAR(0, 12, 103): msg->set(var, WR_VAR(0, 12, 103), Level(100, press), Trange::instant()); break; // Wind direction case WR_VAR(0, 11, 1): msg->set(var, WR_VAR(0, 11, 1), Level(100, press), Trange::instant()); break; // Wind speed case WR_VAR(0, 11, 2): msg->set(var, WR_VAR(0, 11, 2), Level(100, press), Trange::instant()); break; /* Wind shear data at a pressure level */ case WR_VAR(0, 11, 61): msg->set(var, WR_VAR(0, 11, 61), Level(100, press), Trange::instant()); break; case WR_VAR(0, 11, 62): msg->set(var, WR_VAR(0, 11, 62), Level(100, press), Trange::instant()); break; default: WMOImporter::import_var(var); break; } } void TempImporter::import_group(unsigned start, unsigned length) { // Compute vertical level information Level lev; for (unsigned i = 0; i < length && lev.ltype1 == MISSING_INT; ++i) { const Var& var = (*subset)[start + i]; switch (var.code()) { // Height level case WR_VAR(0, 7, 2): case WR_VAR(0, 7, 9): // Geopotential height, for pilots (FIXME: above ground or above msl?) if (var.isset()) lev = Level(102, var.enqd()); break; // Height level converted in mm case WR_VAR(0, 7, 7): if (var.isset()) lev = Level(102, var.enqd() * 1000); break; // Pressure level case WR_VAR(0, 7, 4): if (var.isset()) lev = Level(100, var.enqd()); break; case WR_VAR(0, 10, 3): // Convert geopotential to height if (var.isset()) lev = Level(102, lround(var.enqd() / 9.80665)); break; } } if (lev.ltype1 == MISSING_INT) return; //throw error_consistency("neither B07002 nor B07004 nor B10003 found in sounding group"); // Import all values for (unsigned i = 0; i < length; ++i) { const Var& var = (*subset)[start + i]; if (!var.isset()) { switch (var.code()) { case WR_VAR(0, 8, 1): case WR_VAR(0, 8, 42): // Preserve missing VSS with only the one missing bit set, // to act as a sounding context marker msg->seti(WR_VAR(0, 8, 42), BUFR08042::MISSING, -1, lev, Trange::instant()); break; } continue; } switch (var.code()) { case WR_VAR(0, 4, 16): case WR_VAR(0, 4, 86): msg->set(var, WR_VAR(0, 4, 86), lev, Trange::instant()); break; case WR_VAR(0, 5, 1): case WR_VAR(0, 5, 2): msg->set(var, WR_VAR(0, 5, 1), lev, Trange::instant()); break; case WR_VAR(0, 5, 15): msg->set(var, WR_VAR(0, 5, 15), lev, Trange::instant()); break; case WR_VAR(0, 6, 1): case WR_VAR(0, 6, 2): msg->set(var, WR_VAR(0, 6, 1), lev, Trange::instant()); break; case WR_VAR(0, 6, 15): msg->set(var, WR_VAR(0, 6, 15), lev, Trange::instant()); break; case WR_VAR(0, 8, 1): { // This accounts for weird data that has '1' for VSS unsigned val = convert_BUFR08001_to_BUFR08042(var.enqi()); if (val == BUFR08042::ALL_MISSING) msg->seti(WR_VAR(0, 8, 42), BUFR08042::MISSING, -1, lev, Trange::instant()); else { unique_ptr nvar(newvar(WR_VAR(0, 8, 42), (int)val)); nvar->setattrs(var); msg->set(move(nvar), lev, Trange::instant()); } } break; case WR_VAR(0, 8, 42): msg->set(var, WR_VAR(0, 8, 42), lev, Trange::instant()); break; case WR_VAR(0, 10, 3): msg->set(var, WR_VAR(0, 10, 8), lev, Trange::instant()); break; case WR_VAR(0, 10, 9): msg->set(var, WR_VAR(0, 10, 8), lev, Trange::instant()); break; case WR_VAR(0, 12, 1): case WR_VAR(0, 12, 101): msg->set(var, WR_VAR(0, 12, 101), lev, Trange::instant()); break; case WR_VAR(0, 12, 3): case WR_VAR(0, 12, 103): msg->set(var, WR_VAR(0, 12, 103), lev, Trange::instant()); break; case WR_VAR(0, 7, 4): case WR_VAR(0, 10, 4): msg->set(var, WR_VAR(0, 10, 4), lev, Trange::instant()); break; case WR_VAR(0, 11, 1): case WR_VAR(0, 11, 2): msg->set(var, var.code(), lev, Trange::instant()); break; // Variables from Radar doppler wind profiles case WR_VAR(0, 11, 6): msg->set(var, var.code(), lev, Trange::instant()); break; case WR_VAR(0, 11, 50): msg->set(var, var.code(), lev, Trange::instant()); break; case WR_VAR(0, 33, 2): // Doppler wind profiles transmit quality information inline, // following the variable they refer to. if (i > 0) { // So we look at the varcode of the previous value Varcode prev_code = (*subset)[start + i - 1].code(); switch (prev_code) { // And if it is one of those for which quality info is // set in this way... case WR_VAR(0, 11, 2): case WR_VAR(0, 11, 6): // ...we lookup the variable we previously set in // msg and add the attribute to it if (wreport::Var* prev_var = msg->edit(prev_code, lev, Trange::instant())) prev_var->seta(var); break; } } break; //default: // msg->set(var, var.code(), lev, Trange::instant()); // break; } } } } // namespace wbimporter } // namespace msg } // namespace dballe /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/msg/wr_importers/pollution.cc0000644000175000017500000003356012652630043016644 00000000000000/* * Copyright (C) 2005--2011 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #if 0 // Above ground is ltype = 105, l1 = metri (se undef, cosa metto? Chiedo a // Stortini per un default?) switch (dba_var_code(var)) { cleanup: if (finalvar != NULL) dba_var_delete(finalvar); return err == DBA_OK ? dba_error_ok() : err; } #endif #include "base.h" #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace msg { namespace wr { static double intexp10(unsigned x) { switch (x) { case 0: return 1.0; case 1: return 10.0; case 2: return 100.0; case 3: return 1000.0; case 4: return 10000.0; case 5: return 100000.0; case 6: return 1000000.0; case 7: return 10000000.0; case 8: return 100000000.0; case 9: return 1000000000.0; case 10: return 10000000000.0; case 11: return 100000000000.0; case 12: return 1000000000000.0; case 13: return 10000000000000.0; case 14: return 100000000000000.0; case 15: return 1000000000000000.0; case 16: return 10000000000000000.0; default: error_domain::throwf("computing double value of %u^10 is not yet supported", x); } } #define MISSING_PRESS -1.0 static inline int to_h(double val) { return lround(val / 9.80665); } class PollutionImporter : public WMOImporter { protected: Level lev; Trange tr; int valtype; int decscale; int value; const Var* attr_conf; const Var* attr_cas; const Var* attr_pmc; const Var* finalvar; void import_var(const Var& var); public: PollutionImporter(const msg::Importer::Options& opts) : WMOImporter(opts) {} virtual ~PollutionImporter() {} virtual void init() { WMOImporter::init(); lev = Level(103); tr = Trange(0); valtype = 0; decscale = MISSING_INT; value = 0; attr_conf = NULL; attr_cas = NULL; attr_pmc = NULL; finalvar = NULL; } virtual void run() { // Scan the input variables for (pos = 0; pos < subset->size(); ++pos) { const Var& var = (*subset)[pos]; if (WR_VAR_F(var.code()) != 0) continue; if (var.isset()) import_var(var); } // Create the final pollutant variables by putting all the pieces // together // Use default level and time range if the message did not report it if (lev.l1 == MISSING_INT) lev.l1 = 3000; if (tr.p1 == MISSING_INT) { tr.p1 = -3600; tr.p2 = 3600; } // Create the final variable unique_ptr finalvar = newvar(valtype); // Scale the value and set it if (decscale > 0) finalvar->setd(value * intexp10(decscale)); else finalvar->setd(value / intexp10(-decscale)); // Add the attributes if (attr_conf) finalvar->seta(*attr_conf); if (attr_cas) finalvar->seta(*attr_cas); if (attr_pmc) finalvar->seta(*attr_pmc); // Store it into the dba_msg msg->set(move(finalvar), lev, tr); } MsgType scanType(const Bulletin& bulletin) const { return MSG_POLLUTION; } }; std::unique_ptr Importer::createPollution(const msg::Importer::Options& opts) { return unique_ptr(new PollutionImporter(opts)); } void PollutionImporter::import_var(const Var& var) { switch (var.code()) { /* For this parameter you can give up to 32 characters as a station * name. */ case WR_VAR(0, 1, 19): msg->set_st_name_var(var); break; /* Airbase local code -- Up to 7 characters reflecting the local * station code supplied with the observations. If not given then * leave blank. */ case WR_VAR(0, 1, 212): msg->set_poll_lcode_var(var); break; /* Airbase station code -- 7 character code supplied with AirBase * observations (see Ref 1, II.1.4, page 23). If not supplied then * leave blank.*/ case WR_VAR(0, 1, 213): msg->set_poll_scode_var(var); break; /* GEMS code -- 6 character code suggested at RAQ Paris meeting, * December 2006. First 2 characters to be country code (using * ISO 3166-1-alpha-2 code), next 4 characters to be unique station * number within national boundary for each station (numbering to * be defined and maintained by each GEMS RAQ partner responsible * for collecting observations within each national boundar * invovled)*/ case WR_VAR(0, 1, 214): msg->set_poll_gemscode_var(var); break; /* * Dominant emission source influencing the air pollution * concentrations at the station (based on Ref 1, II.2.2, page 28) * Possible values are: * 0 traffic * 1 industrial * 2 background * 3-6 reserved (do not use) * 7 missing (or unknown) */ case WR_VAR(0, 1, 215): msg->set_poll_source_var(var); break; /* * Type of area in which station is located (based on Ref 1, II.2.1, page 27) * Possible values are: * 0 urban * 1 suburban * 2 rural * 3-6 reserved (do not use) * 7 missing (or unknown) */ case WR_VAR(0, 1, 216): msg->set_poll_atype_var(var); break; /* * Type of terrain in which the station is located (based on table in Ref 1, II.1.12, page 26) * Possible values are: * 0 mountain * 1 valley * 2 seaside * 3 lakeside * 4 plain * 5 hilly terrain * 6-14 reserved (do not use) * 15 missing (or unknown) */ case WR_VAR(0, 1, 217): msg->set_poll_ttype_var(var); break; /* * Height of station above mean sea level and height of sensing * instrument above local ground. Both in metres. If not known than * can be coded as missing value. */ case WR_VAR(0, 7, 30): msg->set_height_station_var(var); break; case WR_VAR(0, 7, 31): lev.l1 = var.enqi(); break; /* Signifies that observation is an average over a certain time period. Value set to 2. */ case WR_VAR(0, 8, 21): if (var.enqi() != 2) error_consistency::throwf("time significance is %d instead of 2", var.enqi()); break; /* * Time period over which the average has been taken (in minutes), * e.g. -60 for average over the previous hour. The period is * relative to the date/time of the observation. */ case WR_VAR(0, 4, 25): // Convert from minutes to seconds tr.p1 = var.enqi() * 60; tr.p2 = -tr.p1; break; /* * VAL stands for validation and signifies that this parameter has * not yet reached operational status at WMO. * Identifier for species observed. * Possible values are: * Code Constituent CAS Registry Number (if applicable) * 0 Ozone (O3) 10028-15-6 * 1 Water vapour (H2O) 7732-18-5 * 2 Methane (CH4) 74-82-8 * 3 Carbon dioxide (CO2) 37210-16-5 * 4 Carbon monoxide (CO) 630-08-0 * 5 Nitrogen dioxide (NO2) 10102-44-0 * 6 Nitrous oxide (N2O) 10024-97-2 * 7 Formaldehyde (HCHO) 50-00-0 * 8 Sulphur dioxide (SO2) 7446-09-5 * 9-24 reserved * 25 Particulate matter < 1.0 microns * 26 Particulate matter < 2.5 microns * 27 Particulate matter < 10 microns * 28 Aerosols (generic) * 29 Smoke (generic) * 30 Crustal material (generic) * 31 Volcanic ash * 32-200 reserved * 201-254 reserved for local use * 255 missing * We may have to propose some new entries to WMO if this does not * cover the range of constituents of the air quality observations. * N.B. Do not code this as missing. This is a key piece of * information in identifying the observed quantity. * * Our target BUFR entries are: * 015192 [SIM] NO Concentration Does not fit in above table: not exported * 015193 [SIM] NO2 Concentration 5 * 015194 [SIM] O3 Concentration 0 * 015195 [SIM] PM10 Concentration 27 */ case WR_VAR(0, 8, 43): switch (var.enqi()) { case 0: valtype = WR_VAR(0, 15, 194); break; case 4: valtype = WR_VAR(0, 15, 196); break; case 5: valtype = WR_VAR(0, 15, 193); break; case 8: valtype = WR_VAR(0, 15, 197); break; case 26: valtype = WR_VAR(0, 15, 198); break; case 27: valtype = WR_VAR(0, 15, 195); break; default: error_consistency::throwf("cannot import constituent %d as there is no mapping for it", var.enqi()); } break; /* * Chemical Abstracts Service (CAS) Registry number of constituent, * if applicable. This parameter is optional and can be coded as a * blank character string. */ case WR_VAR(0, 8, 44): attr_cas = &var; break; /* * If parameter 008043 is coded as 25, 26 or 27, then this * parameter can be used to further categorise the nature of the * particulate matter. * * Possible values are: * 0 Particulate matter (all types) * 1 NO3(-) * 2 NH4(+) * 3 Na(+) * 4 Cl(-) * 5 Ca(2+) * 6 Mg(2+) * 7 K(+) * 8 SO4(2-) * 9-200 reserved * 201-254 reserved for local use * 255 missing */ case WR_VAR(0, 8, 45): attr_pmc = &var; break; /* * A recent feature (still pre-operational at WMO) is the * introduction of scaled quanities specifically to deal with * quantities which may exhibit a large dynamic range. In order to * be able to cover a large dynamic range whilst conserving * precision some specific scale quantities have been introduced * which have an associated decimal scaling factor. The * example_airbase2bufr.f90 code gives an example of a method to * calculate the decimal scaling factor. */ case WR_VAR(0, 8, 90): /* Someone seems to have thought that C fields in BUFR data * section were not crazy enough, and went on reimplementing * them using B fields. So we have to reimplement the same * logic here. * * I'll however ignore resetting the decimal scale because in * this template it is only used for the measured pollutant * value. */ if (decscale == MISSING_INT) { decscale = var.enqi(); /* * Sadly, someone seems to have decided that "all 8 bits to * 1" missing data is the same as encoding -127, so they * encode "all 8 bits to 0 with a reference value of -127" */ if (decscale == -127) decscale = 0; } break; /* * This is the most suitable parameter (that I can find) in BUFR to * represent the concentration of pollutants. The units are * kg/m**3. The example_airbase2bufr.f90 code gives an example of a * method to calculate the decimal scaling factor and scaled mass * density from the observed concentration. To do the backwards * calculation, concentration (kg/m**3) = scaled mass density * * 10**(decimal scaling factor) */ case WR_VAR(0, 15, 23): value = var.enqi(); break; /* * Parameter to give a qualitative measure of the quality of the * observation. Set at the discretion of the encoder given any * information they have either directly from the observation data * set or otherwise. * Possible values are: * 0 Data not suspect * 1 Data slightly suspect * 2 Data highly suspect * 3 Data considered unfit for use * 4-6 Reserved * 7 Quality information not given */ case WR_VAR(0, 33, 3): attr_conf = &var; break; default: WMOImporter::import_var(var); break; } } } // namespace wbimporter } // namespace msg } // namespace dballe /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/msg/wr_importers/base.cc0000644000175000017500000005662312652630043015536 00000000000000/* * dballe/wr_importers/base - Base infrastructure for wreport importers * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "base.h" #include "core/var.h" #include #include #include #define MISSING_BARO -10000.0 #define MISSING_PRESS_STD 0.0 #define MISSING_SENSOR_H -10000.0 #define MISSING_TIME_SIG -10000 using namespace wreport; using namespace std; namespace dballe { namespace msg { namespace wr { static const Trange tr_std_past_wtr3(205, 0, 10800); static const Trange tr_std_past_wtr6(205, 0, 21600); static const Level lev_std_wind(103, 10*1000); static const Trange tr_std_wind(200, 0, 600); static const Trange tr_std_wind_max10m(205, 0, 600); void Importer::init() { ye = mo = da = ho = mi = se = MISSING_INT; } void Importer::import(const wreport::Subset& subset, Msg& msg) { this->subset = ⊂ this->msg = &msg; init(); run(); if (ye == MISSING_INT) msg.set_datetime(Datetime()); else { if (mo == MISSING_INT) throw error_consistency("no month information found in message to import"); if (da == MISSING_INT) throw error_consistency("no day information found in message to import"); if (ho == MISSING_INT) throw error_consistency("no hour information found in message to import"); if (mi == MISSING_INT) throw error_consistency("no minute information found in message to import"); if (se == MISSING_INT) se = 0; // Accept an hour of 24:00:00 and move it to 00:00:00 of the following // day Datetime::normalise_h24(ye, mo, da, ho, mi, se); msg.set_datetime(Datetime(ye, mo, da, ho, mi, se)); } } std::unique_ptr Importer::createSat(const msg::Importer::Options&) { throw error_unimplemented("WB sat Importers"); } void WMOImporter::import_var(const Var& var) { switch (var.code()) { // General bulletin metadata case WR_VAR(0, 1, 1): msg->set_block_var(var); break; case WR_VAR(0, 1, 2): msg->set_station_var(var); break; case WR_VAR(0, 1, 5): case WR_VAR(0, 1, 6): case WR_VAR(0, 1, 11): msg->set_ident_var(var); break; case WR_VAR(0, 1, 12): msg->set_st_dir_var(var); break; case WR_VAR(0, 1, 13): msg->set_st_speed_var(var); break; case WR_VAR(0, 1, 63): msg->set_st_name_icao_var(var); break; case WR_VAR(0, 2, 1): msg->set_st_type_var(var); break; case WR_VAR(0, 1, 15): msg->set_st_name_var(var); break; case WR_VAR(0, 4, 1): ye = var.enqi(); if (var.next_attr()) msg->set_year_var(var); break; case WR_VAR(0, 4, 2): mo = var.enqi(); if (var.next_attr()) msg->set_month_var(var); break; case WR_VAR(0, 4, 3): da = var.enqi(); if (var.next_attr()) msg->set_day_var(var); break; case WR_VAR(0, 4, 4): ho = var.enqi(); if (var.next_attr()) msg->set_hour_var(var); break; case WR_VAR(0, 4, 5): mi = var.enqi(); if (var.next_attr()) msg->set_minute_var(var); break; case WR_VAR(0, 4, 6): se = var.enqi(); if (var.next_attr()) msg->set_second_var(var); break; case WR_VAR(0, 5, 1): case WR_VAR(0, 5, 2): msg->set_latitude_var(var); break; case WR_VAR(0, 6, 1): case WR_VAR(0, 6, 2): msg->set_longitude_var(var); break; } } void LevelContext::init() { height_baro = MISSING_BARO; press_std = MISSING_PRESS_STD; height_sensor = MISSING_SENSOR_H; height_sensor_seen = false; depth = MISSING_SENSOR_H; swell_wave_group = 0; } void LevelContext::peek_var(const wreport::Var& var) { switch (var.code()) { case WR_VAR(0, 7, 4): // Remember the standard level pressure to use later as layer for geopotential press_std = var.enq(MISSING_PRESS_STD); break; case WR_VAR(0, 7, 31): // Remember the height to use later as layer for pressure height_baro = var.enq(MISSING_BARO); break; case WR_VAR(0, 7, 32): // Height to use later as level for whatever needs it height_sensor = MISSING_SENSOR_H; height_sensor = var.enq(MISSING_SENSOR_H); height_sensor_seen = true; break; case WR_VAR(0, 7, 63): depth = var.enq(MISSING_SENSOR_H); break; } } void TimerangeContext::init() { time_period = MISSING_INT; time_period_offset = 0; time_period_seen = false; time_sig = MISSING_TIME_SIG; hour = MISSING_INT; last_B04024_pos = -1; } void TimerangeContext::peek_var(const Var& var, unsigned pos) { if (var.isset()) { switch (var.code()) { case WR_VAR(0, 4, 4): hour = var.enqi(); break; case WR_VAR(0, 4, 24): // Time period in hours if ((int)pos == last_B04024_pos + 1) { // Cope with the weird idea of using B04024 twice to indicate // beginning and end of a period not ending with the SYNOP // reference time if (time_period != MISSING_INT && var.enqi() != 0) { time_period -= var.enqd() * 3600; time_period_offset = var.enqd() * 3600; } } else { time_period = var.enqd() * 3600; time_period_seen = true; time_period_offset = 0; } last_B04024_pos = pos; break; case WR_VAR(0, 4, 25): // Time period in minutes time_period = var.enqd() * 60; time_period_seen = true; time_period_offset = 0; break; case WR_VAR(0, 8, 21): // Time significance time_sig = var.enqi(); // If we get time significance 18 "Radiosonde launch time" // before getting the initial reference time, they are trying // to tell us that they are giving us the radiosonde launch // time: ignore it, since it is already what we gave for // granted. if (hour == MISSING_INT and time_sig == 18) time_sig = MISSING_TIME_SIG; break; } } else { switch (var.code()) { case WR_VAR(0, 4, 4): hour = MISSING_INT; break; case WR_VAR(0, 4, 24): // Time period in hours time_period = MISSING_INT; time_period_offset = 0; time_period_seen = true; break; case WR_VAR(0, 4, 25): // Time period in minutes time_period = MISSING_INT; time_period_offset = 0; time_period_seen = true; break; case WR_VAR(0, 8, 21): // Time significance time_sig = MISSING_TIME_SIG; break; } } } void CloudContext::init() { level = Level::cloud(MISSING_INT, MISSING_INT); } void CloudContext::on_vss(const wreport::Subset& subset, unsigned pos) { /* Vertical significance */ if (pos == 0) throw error_consistency("B08002 found at beginning of message"); Varcode prev = subset[pos - 1].code(); if (prev == WR_VAR(0, 20, 10)) { // Normal cloud data level.ltype2 = 258; level.l2 = 0; return; } if (pos == subset.size() - 1) throw error_consistency("B08002 found at end of message"); Varcode next = subset[pos + 1].code(); switch (next) { case WR_VAR(0, 20, 11): { if (pos >= subset.size() - 3) throw error_consistency("B08002 followed by B20011 found less than 3 places before end of message"); Varcode next2 = subset[pos + 3].code(); if (next2 == WR_VAR(0, 20, 14)) { // Clouds with bases below station level if (level.ltype2 != 263) { level.ltype2 = 263; level.l2 = 1; } else { ++level.l2; } } else { /* Individual cloud groups */ if (level.ltype2 != 259) { level.ltype2 = 259; level.l2 = 1; } else { ++level.l2; } } break; } case WR_VAR(0, 20, 54): // Direction of cloud drift if (level.ltype2 != 260) { level.ltype2 = 260; level.l2 = 1; } else { ++level.l2; } break; default: break; #if 0 /* Vertical significance */ if (pos == 0) throw error_consistency("B08002 found at beginning of message"); if (pos == subset->size() - 1) throw error_consistency("B08002 found at end of message"); Varcode prev = (*subset)[pos - 1].code(); Varcode next = (*subset)[pos + 1].code(); } else if (var.value() == NULL) { level.ltype2 = 0; } else { /* Unless we can detect known buggy situations, raise an error */ if (next != WR_VAR(0, 20, 62)) error_consistency::throwf("Vertical significance %d found in unrecognised context", var.enqi()); } break; #endif } } const Level& CloudContext::clcmch() { if (level.ltype2 == 258) ++level.l2; return level; } ContextChooser::ContextChooser(const LevelContext& level, const TimerangeContext& trange) : level(level), trange(trange), simplified(false), var(0) { } ContextChooser::~ContextChooser() { if (var) delete var; } void ContextChooser::init(Msg& _msg, bool simplified) { this->simplified = simplified; msg = &_msg; } void ContextChooser::ib_start(int shortcut, const Var& var) { v = &shortcutTable[shortcut]; if (this->var) delete this->var; this->var = var_copy_without_unset_attrs(var, v->code).release(); } Level ContextChooser::lev_real(const Level& standard) const { if (level.height_sensor == 0) return Level(1); if (!level.height_sensor_seen) return standard; return level.height_sensor == MISSING_SENSOR_H ? Level(103) : Level(103, level.height_sensor * 1000); } Trange ContextChooser::tr_real(const Trange& standard) const { if (standard.pind == 254) return Trange::instant(); if (!trange.time_period_seen) return standard; return trange.time_period == MISSING_INT ? Trange(standard.pind, 0) : Trange(standard.pind, 0, abs(trange.time_period)); } void ContextChooser::ib_annotate_level() { if (level.height_sensor == MISSING_SENSOR_H) return; var->seta(newvar(WR_VAR(0, 7, 32), level.height_sensor)); } void ContextChooser::ib_annotate_trange() { if (trange.time_period == MISSING_INT) return; var->seta(newvar(WR_VAR(0, 4, 194), abs(trange.time_period))); } void ContextChooser::ib_level_use_shorcut_and_preserve_rest(const Level& standard) { chosen_lev = lev_shortcut(); Level real = lev_real(standard); if (real != chosen_lev && real != standard) ib_annotate_level(); } void ContextChooser::ib_trange_use_shorcut_and_preserve_rest(const Trange& standard) { chosen_tr = tr_shortcut(); Trange real = tr_real(standard); if (real != chosen_tr && real != standard) ib_annotate_trange(); } void ContextChooser::ib_level_use_standard_and_preserve_rest(const Level& standard) { chosen_lev = standard; if (chosen_lev != lev_real(standard)) ib_annotate_level(); } void ContextChooser::ib_trange_use_standard_and_preserve_rest(const Trange& standard) { chosen_tr = standard; if (chosen_tr != tr_real(standard)) ib_annotate_trange(); } void ContextChooser::ib_level_use_shorcut_if_standard_else_real(const Level& standard) { Level shortcut = lev_shortcut(); Level real = lev_real(standard); if (real == shortcut || real == standard) chosen_lev = shortcut; else chosen_lev = real; } void ContextChooser::ib_trange_use_shorcut_if_standard_else_real(const Trange& standard) { Trange shortcut = tr_shortcut(); Trange real = tr_real(standard); if (real == shortcut || real == standard) chosen_tr = shortcut; else chosen_tr = real; } void ContextChooser::ib_set() { unique_ptr handover(var); var = 0; msg->set(move(handover), chosen_lev, chosen_tr); } void ContextChooser::set_gen_sensor(const Var& var, Varcode code, const Level& defaultLevel, const Trange& trange) { Level lev; if (!level.height_sensor_seen || (level.height_sensor != MISSING_SENSOR_H && ( defaultLevel == Level(103, level.height_sensor * 1000) || (defaultLevel.ltype1 == 1 && level.height_sensor == 0)))) msg->set(var, code, defaultLevel, trange); else if (level.height_sensor == MISSING_SENSOR_H) { if (simplified) msg->set(var, code, defaultLevel, trange); else msg->set(var, code, Level(103, MISSING_INT), trange); } else if (simplified) { Var var1(var); var1.seta(auto_ptr(newvar(WR_VAR(0, 7, 32), level.height_sensor).release())); msg->set(var1, code, defaultLevel, trange); } else msg->set(var, code, Level(103, level.height_sensor * 1000), trange); } void ContextChooser::set_gen_sensor(const Var& var, int shortcut) { const MsgVarShortcut& v = shortcutTable[shortcut]; set_gen_sensor(var, shortcut, Level(v.ltype1, v.l1, v.ltype2, v.l2), Trange(v.pind, v.p1, v.p2)); } void ContextChooser::set_gen_sensor(const Var& var, int shortcut, const Trange& tr_std, bool tr_careful) { ib_start(shortcut, var); ib_level_use_shorcut_and_discard_rest(); if (!simplified) ib_trange_use_real(tr_std); else if (tr_careful) ib_trange_use_shorcut_if_standard_else_real(tr_std); else ib_trange_use_shorcut_and_preserve_rest(tr_std); ib_set(); } void ContextChooser::set_gen_sensor(const Var& var, int shortcut, const Level& lev_std, const Trange& tr_std, bool lev_careful, bool tr_careful) { ib_start(shortcut, var); if (!simplified) { ib_level_use_real(lev_std); ib_trange_use_real(tr_std); } else { if (lev_careful) ib_level_use_shorcut_if_standard_else_real(lev_std); else ib_level_use_shorcut_and_preserve_rest(lev_std); if (tr_careful) ib_trange_use_shorcut_if_standard_else_real(tr_std); else ib_trange_use_shorcut_and_preserve_rest(tr_std); } ib_set(); } void ContextChooser::set_baro_sensor(const Var& var, int shortcut) { if (level.height_baro == MISSING_BARO) msg->set_by_id(var, shortcut); else if (simplified) { Var var1(var); var1.seta(newvar(WR_VAR(0, 7, 31), level.height_baro)); msg->set_by_id(var1, shortcut); } else { const MsgVarShortcut& v = shortcutTable[shortcut]; msg->set(var, v.code, Level(102, level.height_baro*1000), Trange(v.pind, v.p1, v.p2)); } } void ContextChooser::set_past_weather(const wreport::Var& var, int shortcut) { ib_start(shortcut, var); ib_level_use_shorcut_and_discard_rest(); if (simplified) ib_trange_use_standard_and_preserve_rest((trange.hour % 6 == 0) ? tr_std_past_wtr6 : tr_std_past_wtr3); else ib_trange_use_real((trange.hour % 6 == 0) ? tr_std_past_wtr6 : tr_std_past_wtr3); ib_set(); } void ContextChooser::set_wind(const wreport::Var& var, int shortcut) { if (trange.time_sig != MISSING_TIME_SIG && trange.time_sig != 2) error_consistency::throwf("Found unsupported time significance %d for wind direction", trange.time_sig); set_gen_sensor(var, shortcut, lev_std_wind, tr_std_wind); } void ContextChooser::set_wind_max(const wreport::Var& var, int shortcut) { set_gen_sensor(var, shortcut, lev_std_wind, tr_std_wind_max10m, false, true); } void ContextChooser::set_pressure(const wreport::Var& var) { if (level.press_std == MISSING_PRESS_STD) msg->set(var, WR_VAR(0, 10, 8), Level(100), Trange::instant()); else msg->set(var, WR_VAR(0, 10, 8), Level(100, level.press_std), Trange::instant()); } void ContextChooser::set_water_temperature(const wreport::Var& var) { if (level.depth == MISSING_SENSOR_H) msg->set(var, WR_VAR(0, 22, 43), Level(1), Trange::instant()); else msg->set(var, WR_VAR(0, 22, 43), Level(160, level.depth * 1000), Trange::instant()); } void ContextChooser::set_swell_waves(const wreport::Var& var) { msg->set(var, var.code(), Level(264, MISSING_INT, 261, level.swell_wave_group), Trange::instant()); } SynopBaseImporter::SynopBaseImporter(const msg::Importer::Options& opts) : WMOImporter(opts), ctx(level, trange) { } void SynopBaseImporter::init() { WMOImporter::init(); clouds.init(); level.init(); trange.init(); ctx.init(*msg, opts.simplified); } void SynopBaseImporter::run() { for (pos = 0; pos < subset->size(); ++pos) { const Var& var = (*subset)[pos]; if (WR_VAR_F(var.code()) != 0) continue; if (WR_VAR_X(var.code()) < 10 || var.code() == WR_VAR(0, 22, 3)) peek_var(var); if (var.isset()) import_var(var); } } void SynopBaseImporter::peek_var(const Var& var) { switch (var.code()) { case WR_VAR(0, 4, 4): case WR_VAR(0, 4, 24): case WR_VAR(0, 4, 25): case WR_VAR(0, 8, 21): trange.peek_var(var, pos); break; case WR_VAR(0, 8, 2): clouds.on_vss(*subset, pos); break; case WR_VAR(0, 7, 4): case WR_VAR(0, 7, 31): case WR_VAR(0, 7, 32): case WR_VAR(0, 7, 63): level.peek_var(var); break; case WR_VAR(0, 22, 3): ++level.swell_wave_group; break; } } void SynopBaseImporter::import_var(const Var& var) { switch (var.code()) { case WR_VAR(0, 8, 2): // Store original VS value as a measured value msg->set(var, WR_VAR(0, 8, 2), clouds.level, Trange::instant()); break; // Ship identification, movement, date/time, horizontal and vertical // coordinates case WR_VAR(0, 7, 1): case WR_VAR(0, 7, 30): msg->set_height_station_var(var); break; case WR_VAR(0, 7, 31): /* Store also in the ana level, so that if the * pressure later is missing we still have * access to the value */ msg->set_height_baro_var(var); break; // Pressure data (complete) case WR_VAR(0, 10, 4): ctx.set_baro_sensor(var, DBA_MSG_PRESS); break; case WR_VAR(0, 10, 51): ctx.set_baro_sensor(var, DBA_MSG_PRESS_MSL); break; case WR_VAR(0, 10, 61): ctx.set_baro_sensor(var, DBA_MSG_PRESS_3H); break; case WR_VAR(0, 10, 62): ctx.set_baro_sensor(var, DBA_MSG_PRESS_24H); break; case WR_VAR(0, 10, 63): ctx.set_baro_sensor(var, DBA_MSG_PRESS_TEND); break; case WR_VAR(0, 10, 3): case WR_VAR(0, 10, 8): case WR_VAR(0, 10, 9): ctx.set_pressure(var); break; // Ship “instantaneous†data // Temperature and humidity data (complete) case WR_VAR(0, 12, 4): case WR_VAR(0, 12, 101): ctx.set_gen_sensor(var, DBA_MSG_TEMP_2M); break; case WR_VAR(0, 12, 6): case WR_VAR(0, 12, 103): ctx.set_gen_sensor(var, DBA_MSG_DEWPOINT_2M); break; case WR_VAR(0, 13, 3): ctx.set_gen_sensor(var, DBA_MSG_HUMIDITY); break; case WR_VAR(0, 12, 2): case WR_VAR(0, 12, 102): ctx.set_gen_sensor(var, DBA_MSG_WET_TEMP_2M); break; // Visibility data (complete) case WR_VAR(0, 20, 1): ctx.set_gen_sensor(var, DBA_MSG_VISIBILITY); break; // Precipitation past 24h (complete) case WR_VAR(0, 13, 19): ctx.set_gen_sensor(var, DBA_MSG_TOT_PREC1); break; case WR_VAR(0, 13, 20): ctx.set_gen_sensor(var, DBA_MSG_TOT_PREC3); break; case WR_VAR(0, 13, 21): ctx.set_gen_sensor(var, DBA_MSG_TOT_PREC6); break; case WR_VAR(0, 13, 22): ctx.set_gen_sensor(var, DBA_MSG_TOT_PREC12); break; case WR_VAR(0, 13, 23): ctx.set_gen_sensor(var, DBA_MSG_TOT_PREC24); break; // Cloud data case WR_VAR(0, 20, 10): msg->set_cloud_n_var(var); break; // Individual cloud layers or masses (complete) // Clouds with bases below station level (complete) // Direction of cloud drift (complete) case WR_VAR(0, 20, 11): case WR_VAR(0, 20, 13): case WR_VAR(0, 20, 17): case WR_VAR(0, 20, 54): msg->set(var, var.code(), clouds.level, Trange::instant()); break; case WR_VAR(0, 20, 12): // CH CL CM msg->set(var, WR_VAR(0, 20, 12), clouds.clcmch(), Trange::instant()); break; // Present and past weather (complete) case WR_VAR(0, 20, 3): msg->set_pres_wtr_var(var); break; case WR_VAR(0, 20, 4): ctx.set_past_weather(var, DBA_MSG_PAST_WTR1_6H); break; case WR_VAR(0, 20, 5): ctx.set_past_weather(var, DBA_MSG_PAST_WTR2_6H); break; // Precipitation measurement (complete) case WR_VAR(0, 13, 11): ctx.set_gen_sensor(var, WR_VAR(0, 13, 11), Level(1), Trange(1, 0, abs(trange.time_period))); break; // Extreme temperature data case WR_VAR(0, 12, 111): ctx.set_gen_sensor(var, WR_VAR(0, 12, 101), Level(1), Trange(2, -abs(trange.time_period_offset), abs(trange.time_period))); break; case WR_VAR(0, 12, 112): ctx.set_gen_sensor(var, WR_VAR(0, 12, 101), Level(1), Trange(3, -abs(trange.time_period_offset), abs(trange.time_period))); break; // Wind data (complete) case WR_VAR(0, 2, 2): msg->set_wind_inst_var(var); break; /* Note B/C 1.10.5.3.2 Calm shall be reported by * setting wind direction to 0 and wind speed to 0. * Variable shall be reported by setting wind direction * to 0 and wind speed to a positive value, not a * missing value indicator. */ case WR_VAR(0, 11, 1): case WR_VAR(0, 11, 11): ctx.set_wind(var, DBA_MSG_WIND_DIR); break; case WR_VAR(0, 11, 2): case WR_VAR(0, 11, 12): ctx.set_wind(var, DBA_MSG_WIND_SPEED); break; case WR_VAR(0, 11, 43): ctx.set_wind_max(var, DBA_MSG_WIND_GUST_MAX_DIR); break; case WR_VAR(0, 11, 41): ctx.set_wind_max(var, DBA_MSG_WIND_GUST_MAX_SPEED); break; case WR_VAR(0, 12, 5): msg->set_wet_temp_2m_var(var); break; case WR_VAR(0, 10,197): msg->set_height_anem_var(var); break; default: WMOImporter::import_var(var); break; } } } // namespace wr } // namespace msg } // namespace dballe /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/msg/wr_importers/synop.cc0000644000175000017500000000770512652630043015771 00000000000000/* * Copyright (C) 2005--2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "base.h" #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace msg { namespace wr { namespace { class SynopImporter : public SynopBaseImporter { protected: virtual void import_var(const Var& var); public: SynopImporter(const msg::Importer::Options& opts) : SynopBaseImporter(opts) {} virtual ~SynopImporter() {} MsgType scanType(const Bulletin& bulletin) const { switch (bulletin.data_category) { case 0: return MSG_SYNOP; default: return MSG_GENERIC; break; } } }; void SynopImporter::import_var(const Var& var) { switch (var.code()) { // Direction and elevation of cloud (complete) case WR_VAR(0, 5, 21): msg->set(var, WR_VAR(0, 5, 21), Level::cloud(262, 0), Trange::instant()); break; case WR_VAR(0, 7, 21): msg->set(var, WR_VAR(0, 7, 21), Level::cloud(262, 0), Trange::instant()); break; // Cloud type is handled by the generic cloud type handler // State of ground, snow depth, ground minimum temperature (complete) case WR_VAR(0, 20, 62): msg->set_state_ground_var(var); break; case WR_VAR(0, 13, 13): msg->set_tot_snow_var(var); break; case WR_VAR(0, 12, 113): msg->set(var, WR_VAR(0, 12, 121), Level(1), Trange(3, 0, 43200)); break; // Basic synoptic "period" data // Sunshine data (complete) case WR_VAR(0, 14, 31): msg->set(var, WR_VAR(0, 14, 31), Level(1), Trange(1, 0, abs(trange.time_period))); break; // Evaporation data case WR_VAR(0, 2, 4): msg->set(var, WR_VAR(0, 2, 4), Level(1), Trange::instant()); break; case WR_VAR(0, 13, 33): if (trange.time_period == MISSING_INT) msg->set(var, WR_VAR(0, 13, 33), Level(1), Trange(1)); else msg->set(var, WR_VAR(0, 13, 33), Level(1), Trange(1, 0, abs(trange.time_period))); break; // Radiation data case WR_VAR(0, 14, 2): case WR_VAR(0, 14, 4): case WR_VAR(0, 14, 16): case WR_VAR(0, 14, 28): case WR_VAR(0, 14, 29): case WR_VAR(0, 14, 30): if (trange.time_period == MISSING_INT) msg->set(var, var.code(), Level(1), Trange(1)); else msg->set(var, var.code(), Level(1), Trange(1, 0, abs(trange.time_period))); break; // Temperature change case WR_VAR(0, 12, 49): msg->set(var, WR_VAR(0, 12, 49), Level(1), Trange(4, -abs(trange.time_period_offset), abs(trange.time_period))); break; case WR_VAR(0, 22, 42): msg->set_water_temp_var(var); break; case WR_VAR(0, 12, 5): msg->set_wet_temp_2m_var(var); break; case WR_VAR(0, 10,197): msg->set_height_anem_var(var); break; default: SynopBaseImporter::import_var(var); break; } } } // anonynmous namespace std::unique_ptr Importer::createSynop(const msg::Importer::Options& opts) { return unique_ptr(new SynopImporter(opts)); } } // namespace wbimporter } // namespace msg } // namespace dballe /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/msg/wr_importers/metar.cc0000644000175000017500000001002412652630043015715 00000000000000/* * Copyright (C) 2005--2011 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "base.h" #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace msg { namespace wr { #define MISSING_SENSOR_H -10000 class MetarImporter : public WMOImporter { protected: double height_sensor; void peek_var(const Var& var); void import_var(const Var& var); void set_gen_sensor(const Var& var, Varcode code, const Level& defaultLevel, const Trange& trange) { if (height_sensor == MISSING_SENSOR_H || defaultLevel == Level(103, height_sensor * 1000)) msg->set(var, code, defaultLevel, trange); else if (opts.simplified) { Var var1(var); var1.seta(auto_ptr(newvar(WR_VAR(0, 7, 32), height_sensor).release())); msg->set(var1, code, defaultLevel, trange); } else msg->set(var, code, Level(103, height_sensor * 1000), trange); } void set_gen_sensor(const Var& var, int shortcut) { const MsgVarShortcut& v = shortcutTable[shortcut]; set_gen_sensor(var, v.code, Level(v.ltype1, v.l1, v.ltype2, v.l2), Trange(v.pind, v.p1, v.p2)); } public: MetarImporter(const msg::Importer::Options& opts) : WMOImporter(opts) {} virtual ~MetarImporter() {} virtual void init() { WMOImporter::init(); height_sensor = MISSING_SENSOR_H; } virtual void run() { for (pos = 0; pos < subset->size(); ++pos) { const Var& var = (*subset)[pos]; if (WR_VAR_F(var.code()) != 0) continue; if (WR_VAR_X(var.code()) < 10) peek_var(var); if (var.isset()) import_var(var); } } MsgType scanType(const Bulletin& bulletin) const { return MSG_METAR; } }; std::unique_ptr Importer::createMetar(const msg::Importer::Options& opts) { return unique_ptr(new MetarImporter(opts)); } void MetarImporter::peek_var(const Var& var) { switch (var.code()) { // Context items case WR_VAR(0, 7, 6): if (var.isset()) height_sensor = var.enqi(); else height_sensor = MISSING_SENSOR_H; break; } } void MetarImporter::import_var(const Var& var) { switch (var.code()) { case WR_VAR(0, 7, 1): msg->set_height_station_var(var); break; case WR_VAR(0, 11, 1): set_gen_sensor(var, DBA_MSG_WIND_DIR); break; case WR_VAR(0, 11, 16): set_gen_sensor(var, DBA_MSG_EX_CCW_WIND); break; case WR_VAR(0, 11, 17): set_gen_sensor(var, DBA_MSG_EX_CW_WIND); break; case WR_VAR(0, 11, 2): set_gen_sensor(var, DBA_MSG_WIND_SPEED); break; case WR_VAR(0, 11, 41): set_gen_sensor(var, DBA_MSG_WIND_SPEED); break; case WR_VAR(0, 12, 1): set_gen_sensor(var, DBA_MSG_TEMP_2M); break; case WR_VAR(0, 12, 3): set_gen_sensor(var, DBA_MSG_DEWPOINT_2M); break; case WR_VAR(0, 10, 52): set_gen_sensor(var, DBA_MSG_QNH); break; case WR_VAR(0, 20, 9): set_gen_sensor(var, DBA_MSG_METAR_WTR); break; default: WMOImporter::import_var(var); break; } } } // namespace wbimporter } // namespace msg } // namespace dballe /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/msg/wr_importers/sat.cc0000644000175000017500000001461012652630043015401 00000000000000/* * DB-ALLe - Archive for punctual meteorological data * * Copyright (C) 2005,2006 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "dballe/msg/msg.h" #include "dballe/bufrex/msg.h" #include dba_err bufrex_copy_to_sat(dba_msg msg, bufrex_msg raw, bufrex_subset sset) { dba_err err = DBA_OK; int i; int l1 = -1; int id_satid = 0, id_sensorid = 0; dba_var scanline = NULL, fov = NULL, framecount = NULL, wavenum = NULL, chqf = NULL; dba_var copy = NULL; char ident[10]; switch (raw->localsubtype) { #if 0 case 142: msg->type = MSG_AIREP; break; case 144: msg->type = MSG_AMDAR; break; case 145: msg->type = MSG_ACARS; break; #endif default: msg->type = MSG_SAT; break; } for (i = 0; i < sset->vars_count; i++) { dba_var var = sset->vars[i]; if (dba_var_value(var) == NULL) continue; switch (dba_var_code(var)) { // 001007 SATELLITE IDENTIFIER(CODE TABLE 1007): 3 case WR_VAR(0, 1, 7): DBA_RUN_OR_RETURN(dba_var_enqi(var, &id_satid)); break; // 002048 SATELLITE SENSOR INDICATOR(CODE TABLE 2048): 0 case WR_VAR(0, 2, 48): DBA_RUN_OR_RETURN(dba_var_enqi(var, &id_sensorid)); break; // -> Ident // 005040 ORBIT NUMBER(NUMERIC): 1 case WR_VAR(0, 5, 40): DBA_RUN_OR_RETURN(dba_msg_set(msg, var, WR_VAR(0, 5, 40), 8, 0, 0, 0, 254, 0, 0)); break; // -> Data #if 0 -- Ignored 025075 SATELLITE ANTENNA CORRECTION VERSION NUMBER(NUMERIC): (undef) #endif // 005041 SCAN LINE NUMBER(NUMERIC): 211 case WR_VAR(0, 5, 41): scanline = var; break; // 005043 FIELD OF VIEW NUMBER(NUMERIC): 0 case WR_VAR(0, 5, 43): fov = var; break; // 025070 MAJOR FRAME COUNT(NUMERIC): (undef) case WR_VAR(0, 25, 70): framecount = var; break; // -> Attrs #if 0 -- Ignored 033030 SCAN LINE STATUS FLAGS FOR ATOVS(FLAG TABLE 33030): 0 033031 SCAN LINE QUALITY FLAGS FOR ATOVS(FLAG TABLE 33031): 262144 #endif case WR_VAR(0, 4, 1): DBA_RUN_OR_RETURN(dba_msg_set_year_var(msg, var)); break; case WR_VAR(0, 4, 2): DBA_RUN_OR_RETURN(dba_msg_set_month_var(msg, var)); break; case WR_VAR(0, 4, 3): DBA_RUN_OR_RETURN(dba_msg_set_day_var(msg, var)); break; case WR_VAR(0, 4, 4): DBA_RUN_OR_RETURN(dba_msg_set_hour_var(msg, var)); break; case WR_VAR(0, 4, 5): DBA_RUN_OR_RETURN(dba_msg_set_minute_var(msg, var)); break; // TODO: 004006 SECOND(SECOND): 22.522000 does not fit in normal second case WR_VAR(0, 5, 1): case WR_VAR(0, 5, 2): DBA_RUN_OR_RETURN(dba_msg_set_latitude_var(msg, var)); break; case WR_VAR(0, 6, 1): case WR_VAR(0, 6, 2): DBA_RUN_OR_RETURN(dba_msg_set_longitude_var(msg, var)); break; // TODO: 007001 HEIGHT OF STATION(M): 830900.000000 does not fit in normal height //case WR_VAR(0, 7, 1): DBA_RUN_OR_RETURN(dba_msg_set_height_var(msg, var)); break; // 007024 SATELLITE ZENITH ANGLE(DEGREE): 56.830000 case WR_VAR(0, 7, 24): DBA_RUN_OR_RETURN(dba_msg_set(msg, var, WR_VAR(0, 7, 24), 8, 0, 0, 0, 254, 0, 0)); break; // 005021 BEARING OR AZIMUTH(DEGREE TRUE): 28.650000 case WR_VAR(0, 5, 21): DBA_RUN_OR_RETURN(dba_msg_set(msg, var, WR_VAR(0, 5, 21), 8, 0, 0, 0, 254, 0, 0)); break; // 007025 SOLAR ZENITH ANGLE(DEGREE): 74.240000 case WR_VAR(0, 7, 25): DBA_RUN_OR_RETURN(dba_msg_set(msg, var, WR_VAR(0, 7, 25), 8, 0, 0, 0, 254, 0, 0)); break; // 005022 SOLAR AZIMUTH(DEGREE TRUE): 273.710000 case WR_VAR(0, 5, 22): DBA_RUN_OR_RETURN(dba_msg_set(msg, var, WR_VAR(0, 5, 22), 8, 0, 0, 0, 254, 0, 0)); break; // -> data // TODO: 033033 FIELD OF VIEW QUALITY FLAGS FOR ATOVS(FLAG TABLE 33033): (undef) // -> ? #if 0 -- Ignored 002151 RADIOMETER IDENTIFIER(CODE TABLE 2151): 0 012064 INSTRUMENT TEMPERATURE(K): (undef) 002151 RADIOMETER IDENTIFIER(CODE TABLE 2151): 3 012064 INSTRUMENT TEMPERATURE(K): (undef) 002151 RADIOMETER IDENTIFIER(CODE TABLE 2151): 4 012064 INSTRUMENT TEMPERATURE(K): (undef) 002151 RADIOMETER IDENTIFIER(CODE TABLE 2151): 6 012064 INSTRUMENT TEMPERATURE(K): (undef) #endif // 002150 TOVS/ATOVS/HIRS INSTRUMENT CHANNEL NUMBER(CODE TABLE 2150): 1 case WR_VAR(0, 2, 150): DBA_RUN_OR_RETURN(dba_var_enqi(var, &l1)); break; // -> level (8, x, 0) // 025076 LOG-10 OF (TEMP-RAD CENTRAL WAVENUMBER) FOR ATOVS(LOGM-1): 4.825342 case WR_VAR(0, 25, 76): wavenum = var; break; // -> attr #if 0 -- Ignored 025077 BANDWIDTH CORRECTION COEFFICIENT 1 FOR ATOVS(NUMERIC): -0.000250 025078 BANDWIDTH CORRECTION COEFFICIENT 2 FOR ATOVS(NUMERIC): 0.999990 #endif // 033032 CHANNEL QUALITY FLAGS FOR ATOVS(FLAG TABLE 33032): 0 case WR_VAR(0, 33, 32): chqf = var; break; // -> attr // 012063 BRIGHTNESS TEMPERATURE(K): 241.100000 case WR_VAR(0, 12, 63): { if (l1 == -1) return dba_error_consistency("channel number not found in incoming message"); DBA_RUN_OR_RETURN(dba_var_copy(var, ©)); if (scanline != NULL) DBA_RUN_OR_GOTO(cleanup, dba_var_seta(copy, scanline)); if (fov != NULL) DBA_RUN_OR_GOTO(cleanup, dba_var_seta(copy, fov)); if (framecount != NULL) DBA_RUN_OR_GOTO(cleanup, dba_var_seta(copy, framecount)); if (wavenum != NULL) DBA_RUN_OR_GOTO(cleanup, dba_var_seta(copy, wavenum)); if (chqf != NULL) DBA_RUN_OR_GOTO(cleanup, dba_var_seta(copy, chqf)); DBA_RUN_OR_GOTO(cleanup, dba_msg_set(msg, copy, WR_VAR(0, 12, 63), 8, l1, 0, 0, 254, 0, 0)); dba_var_delete(copy); copy = NULL; break; } // -> data } } snprintf(ident, 6, "%03d%02d", id_satid, id_sensorid); DBA_RUN_OR_RETURN(dba_msg_set_ident(msg, ident, -1)); cleanup: if (copy != NULL) dba_var_delete(copy); return err == DBA_OK ? dba_error_ok() : err; } /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/msg/wr_importers/ship.cc0000644000175000017500000000764212652630043015564 00000000000000/* * Copyright (C) 2005--2013 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "base.h" #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace msg { namespace wr { namespace { class ShipImporter : public SynopBaseImporter { protected: virtual void import_var(const Var& var); public: ShipImporter(const msg::Importer::Options& opts) : SynopBaseImporter(opts) {} virtual ~ShipImporter() {} MsgType scanType(const Bulletin& bulletin) const { switch (bulletin.data_category) { case 1: switch (bulletin.data_subcategory_local) { case 21: return MSG_BUOY; case 9: case 11: case 12: case 13: case 14: case 19: return MSG_SHIP; case 0: { // Guess looking at the variables if (bulletin.subsets.empty()) throw error_consistency("trying to import a SYNOP message with no data subset"); const Subset& subset = bulletin.subsets[0]; if (subset.size() > 1 && subset[0].code() == WR_VAR(0, 1, 5)) return MSG_BUOY; else return MSG_SHIP; } default: return MSG_SHIP; } break; default: return MSG_GENERIC; break; } } }; void ShipImporter::import_var(const Var& var) { switch (var.code()) { // Icing and ice case WR_VAR(0, 20, 31): case WR_VAR(0, 20, 32): case WR_VAR(0, 20, 33): case WR_VAR(0, 20, 34): case WR_VAR(0, 20, 35): case WR_VAR(0, 20, 36): case WR_VAR(0, 20, 37): case WR_VAR(0, 20, 38): msg->set(var, var.code(), Level(1), Trange::instant()); break; // Ship marine data case WR_VAR(0, 2, 38): msg->set(var, var.code(), Level(), Trange()); break; case WR_VAR(0, 2, 39): msg->set(var, var.code(), Level(), Trange()); break; case WR_VAR(0, 22, 42): case WR_VAR(0, 22, 43): ctx.set_water_temperature(var); break; // Waves case WR_VAR(0, 22, 1): case WR_VAR(0, 22, 11): case WR_VAR(0, 22, 21): case WR_VAR(0, 22, 2): case WR_VAR(0, 22, 12): case WR_VAR(0, 22, 22): msg->set(var, var.code(), Level(1), Trange::instant()); break; break; // D03023 swell waves (2 grups) case WR_VAR(0, 22, 3): // Direction of swell waves case WR_VAR(0, 22, 13): // Period of swell waves case WR_VAR(0, 22, 23): // Height of swell waves ctx.set_swell_waves(var); break; default: SynopBaseImporter::import_var(var); break; } } } // anonynmous namespace std::unique_ptr Importer::createShip(const msg::Importer::Options& opts) { return unique_ptr(new ShipImporter(opts)); } } // namespace wbimporter } // namespace msg } // namespace dballe /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/msg/wr_importers/flight.cc0000644000175000017500000002000212652630043016057 00000000000000/* * Copyright (C) 2005--2011 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "base.h" #include "dballe/core/var.h" #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace msg { namespace wr { class FlightImporter : public WMOImporter { protected: Level lev; std::vector deferred; const Var* b01006; const Var* b01008; void import_var(const Var& var); public: FlightImporter(const msg::Importer::Options& opts) : WMOImporter(opts) {} virtual ~FlightImporter() { // If there are leftover variables in deferred, deallocate them for (std::vector::iterator i = deferred.begin(); i != deferred.end(); ++i) if (*i) delete *i; } virtual void init() { WMOImporter::init(); lev = Level(); deferred.clear(); b01006 = b01008 = NULL; } void acquire(const Var& var) { if (lev.ltype1 == MISSING_INT) { // If we don't have a level yet, defer adding the variable until we // have one unique_ptr copy(var_copy_without_unset_attrs(var)); deferred.push_back(copy.release()); } else msg->set(var, var.code(), lev, Trange::instant()); } void acquire(const Var& var, Varcode code) { if (lev.ltype1 == MISSING_INT) { // If we don't have a level yet, defer adding the variable until we // have one unique_ptr copy(var_copy_without_unset_attrs(var, code)); deferred.push_back(copy.release()); } else msg->set(var, code, lev, Trange::instant()); } void set_level(const Level& newlev) { if (lev.ltype1 != MISSING_INT) error_consistency::throwf("found two flight levels: %s and %s", lev.describe().c_str(), newlev.describe().c_str()); lev = newlev; // Flush deferred variables for (vector::iterator i = deferred.begin(); i != deferred.end(); ++i) { unique_ptr var(*i); *i = 0; msg->set(move(var), lev, Trange::instant()); } deferred.clear(); } virtual void run() { for (pos = 0; pos < subset->size(); ++pos) { const Var& var = (*subset)[pos]; if (WR_VAR_F(var.code()) != 0) continue; if (var.isset()) import_var(var); } if (b01008) { msg->set_ident_var(*b01008); if (b01006) acquire(*b01006); } else if (b01006) msg->set_ident_var(*b01006); } MsgType scanTypeFromVars(const Subset& subset) const { for (unsigned i = 0; i < subset.size(); ++i) { switch (subset[i].code()) { case WR_VAR(0, 2, 65): // ACARS GROUND RECEIVING STATION if (subset[0].isset()) return MSG_ACARS; break; } } return MSG_AMDAR; } MsgType scanType(const Bulletin& bulletin) const { switch (bulletin.data_subcategory_local) { case 142: return MSG_AIREP; case 144: return MSG_AMDAR; case 145: return MSG_ACARS; default: // Scan for the presence of significant B codes if (bulletin.subsets.empty()) return MSG_GENERIC; return scanTypeFromVars(bulletin.subsets[0]); } } }; std::unique_ptr Importer::createFlight(const msg::Importer::Options& opts) { return unique_ptr(new FlightImporter(opts)); } void FlightImporter::import_var(const Var& var) { switch (var.code()) { case WR_VAR(0, 1, 6): b01006 = &var; break; case WR_VAR(0, 1, 8): b01008 = &var; break; case WR_VAR(0, 1, 23): acquire(var); break; case WR_VAR(0, 2, 1): acquire(var); break; case WR_VAR(0, 2, 2): acquire(var); break; case WR_VAR(0, 2, 5): acquire(var); break; case WR_VAR(0, 2, 61): acquire(var); break; case WR_VAR(0, 2, 62): acquire(var); break; case WR_VAR(0, 2, 63): acquire(var); break; case WR_VAR(0, 2, 64): acquire(var); break; case WR_VAR(0, 2, 70): acquire(var); break; case WR_VAR(0, 7, 2): // Specific Altitude Above Mean Sea Level in mm set_level(Level(102, var.enqd() * 1000)); acquire(var, WR_VAR(0, 7, 30)); break; case WR_VAR(0, 7, 4): // Isobaric Surface in Pa if (lev.ltype1 == MISSING_INT) set_level(Level(100, var.enqd())); acquire(var, WR_VAR(0, 10, 4)); break; case WR_VAR(0, 7, 10): // Flight level if (opts.simplified) { // Convert to pressure using formula from // http://www.wmo.int/pages/prog/www/IMOP/publications/CIMO-Guide/CIMO%20Guide%207th%20Edition,%202008/Part%20II/Chapter%203.pdf double p_hPa = 1013.25 * pow(1.0 - 0.000001 * 6.8756 * var.enqd() * 3.28084, 5.2559); set_level(Level(100, round(p_hPa * 100))); } else // Specific Altitude Above Mean Sea Level in mm set_level(Level(102, var.enqd() * 1000)); acquire(var, WR_VAR(0, 7, 30)); break; case WR_VAR(0, 8, 4): acquire(var); break; case WR_VAR(0, 8, 9): acquire(var); break; case WR_VAR(0, 8, 21): acquire(var); break; case WR_VAR(0, 11, 1): acquire(var); break; case WR_VAR(0, 11, 2): acquire(var); break; case WR_VAR(0, 11, 31): acquire(var); break; case WR_VAR(0, 11, 32): acquire(var); break; case WR_VAR(0, 11, 33): acquire(var); break; case WR_VAR(0, 11, 34): acquire(var); break; case WR_VAR(0, 11, 35): acquire(var); break; case WR_VAR(0, 11, 36): acquire(var); break; case WR_VAR(0, 11, 37): acquire(var); break; case WR_VAR(0, 11, 39): acquire(var); break; case WR_VAR(0, 11, 77): acquire(var); break; case WR_VAR(0, 12, 1): acquire(var, WR_VAR(0, 12, 101)); break; case WR_VAR(0, 12,101): acquire(var); break; case WR_VAR(0, 12, 3): acquire(var, WR_VAR(0, 12, 103)); break; case WR_VAR(0, 12,103): acquire(var); break; case WR_VAR(0, 13, 2): acquire(var); break; case WR_VAR(0, 13, 3): acquire(var); break; case WR_VAR(0, 20, 41): acquire(var); break; case WR_VAR(0, 20, 42): acquire(var); break; case WR_VAR(0, 20, 43): acquire(var); break; case WR_VAR(0, 20, 44): acquire(var); break; case WR_VAR(0, 20, 45): acquire(var); break; case WR_VAR(0, 33, 25): acquire(var); break; // TODO: repeated 011075 MEAN TURBULENCE INTENSITY (EDDY DISSIPATION RATE)[M**(2/3)/S] // TODO: repeated 011076 PEAK TURBULENCE INTENSITY (EDDY DISSIPATION RATE)[M**(2/3)/S] default: WMOImporter::import_var(var); break; } } } // namespace wbimporter } // namespace msg } // namespace dballe /* vim:set ts=4 sw=4: */ dballe-7.7/dballe/msg/wr_importers/generic.cc0000644000175000017500000001350612652630043016231 00000000000000/* * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "base.h" #include "dballe/core/var.h" #include #include #include #include using namespace wreport; using namespace std; namespace dballe { namespace msg { namespace wr { class GenericImporter : public Importer { protected: Level lev; Trange tr; /// Import an undefined value void import_defined(const Var& var); /// Import a defined value, which can be a variable or context void import_undef(const Var& var); /// Import a defined value, with the context being properly set void import_var(const Var& var); public: GenericImporter(const msg::Importer::Options& opts) : Importer(opts) {} virtual ~GenericImporter() {} void init() override { Importer::init(); lev = Level(); tr = Trange(); } void run() override { for (size_t pos = 0; pos < subset->size(); ++pos) { const Var& var = (*subset)[pos]; // Skip non-variable entries if (WR_VAR_F(var.code()) != 0) continue; // Special processing for undefined variables if (!var.isset()) { // Also skip attributes of undefined variables if there are // some following for ( ; pos + 1 < subset->size() && WR_VAR_X((*subset)[pos + 1].code()) == 33; ++pos) ; import_undef(var); continue; } // A variable with a value: add attributes to it if any are // found if (pos + 1 < subset->size() && WR_VAR_X((*subset)[pos + 1].code()) == 33) { Var copy(var); for ( ; pos + 1 < subset->size() && WR_VAR_X((*subset)[pos + 1].code()) == 33; ++pos) copy.seta((*subset)[pos + 1]); import_defined(copy); } else import_defined(var); } } MsgType scanType(const Bulletin&) const override { return MSG_GENERIC; } }; std::unique_ptr Importer::createGeneric(const msg::Importer::Options& opts) { return unique_ptr(new GenericImporter(opts)); } void GenericImporter::import_undef(const Var& var) { switch (var.code()) { case WR_VAR(0, 4, 192): tr.pind = MISSING_INT; break; case WR_VAR(0, 4, 193): tr.p1 = MISSING_INT; break; case WR_VAR(0, 4, 194): tr.p2 = MISSING_INT; break; case WR_VAR(0, 7, 192): lev.ltype1 = MISSING_INT; break; case WR_VAR(0, 7, 193): lev.l1 = MISSING_INT; break; case WR_VAR(0, 7, 194): lev.l2 = MISSING_INT; break; case WR_VAR(0, 7, 195): lev.ltype2 = MISSING_INT; break; } } void GenericImporter::import_defined(const Var& var) { switch (var.code()) { case WR_VAR(0, 4, 192): tr.pind = var.enqi(); break; case WR_VAR(0, 4, 193): tr.p1 = var.enqi(); break; case WR_VAR(0, 4, 194): tr.p2 = var.enqi(); break; case WR_VAR(0, 7, 192): lev.ltype1 = var.enqi(); break; case WR_VAR(0, 7, 193): lev.l1 = var.enqi(); break; case WR_VAR(0, 7, 194): lev.l2 = var.enqi(); break; case WR_VAR(0, 7, 195): lev.ltype2 = var.enqi(); break; case WR_VAR(0, 1, 194): if (var.isset()) { // Set the rep memo if we found it const char* repmemo = var.enqc(); msg->type = Msg::type_from_repmemo(repmemo); msg->set_rep_memo(repmemo, -1); } break; default: import_var(var); break; } } void GenericImporter::import_var(const Var& var) { // Adjust station info level for pre-dballe-5.0 generics if (lev.ltype1 == 257) { lev = Level(); tr = Trange(); } switch (var.code()) { // Legacy variable conversions case WR_VAR(0, 8, 1): { unique_ptr nvar(newvar(WR_VAR(0, 8, 42), (int)convert_BUFR08001_to_BUFR08042(var.enqi()))); nvar->setattrs(var); msg->set(move(nvar), lev, tr); break; } // Datetime entries that may have attributes to store case WR_VAR(0, 4, 1): ye = var.enqi(); if (var.next_attr()) msg->set_year_var(var); break; case WR_VAR(0, 4, 2): mo = var.enqi(); if (var.next_attr()) msg->set_month_var(var); break; case WR_VAR(0, 4, 3): da = var.enqi(); if (var.next_attr()) msg->set_day_var(var); break; case WR_VAR(0, 4, 4): ho = var.enqi(); if (var.next_attr()) msg->set_hour_var(var); break; case WR_VAR(0, 4, 5): mi = var.enqi(); if (var.next_attr()) msg->set_minute_var(var); break; case WR_VAR(0, 4, 6): se = var.enqi(); if (var.next_attr()) msg->set_second_var(var); break; // Anything else default: msg->set(var, map_code_to_dballe(var.code()), lev, tr); break; } } } } } dballe-7.7/dballe/msg/wr_importers/base.h0000644000175000017500000001445112652630043015371 00000000000000/* * dballe/wr_importers/base - Base infrastructure for wreport importers * * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #ifndef DBALLE_MSG_WRIMPORTER_BASE_H #define DBALLE_MSG_WRIMPORTER_BASE_H #include #include #include namespace wreport { struct Subset; struct Bulletin; struct Var; } namespace dballe { namespace msg { namespace wr { class Importer { protected: const msg::Importer::Options& opts; const wreport::Subset* subset; Msg* msg; int ye, mo, da, ho, mi, se; virtual void init(); virtual void run() = 0; public: Importer(const msg::Importer::Options& opts) : opts(opts) {} virtual ~Importer() {} virtual MsgType scanType(const wreport::Bulletin& bulletin) const = 0; void import(const wreport::Subset& subset, Msg& msg); static std::unique_ptr createSynop(const msg::Importer::Options&); static std::unique_ptr createShip(const msg::Importer::Options&); static std::unique_ptr createMetar(const msg::Importer::Options&); static std::unique_ptr createTemp(const msg::Importer::Options&); static std::unique_ptr createPilot(const msg::Importer::Options&); static std::unique_ptr createFlight(const msg::Importer::Options&); static std::unique_ptr createSat(const msg::Importer::Options&); static std::unique_ptr createPollution(const msg::Importer::Options&); static std::unique_ptr createGeneric(const msg::Importer::Options&); }; class WMOImporter : public Importer { protected: unsigned pos; void import_var(const wreport::Var& var); virtual void init() { pos = 0; Importer::init(); } public: WMOImporter(const msg::Importer::Options& opts) : Importer(opts) {} virtual ~WMOImporter() {} }; /// Keep track of level context changes struct LevelContext { double height_baro; double press_std; double height_sensor; double depth; bool height_sensor_seen; bool swell_wave_group; void init(); void peek_var(const wreport::Var& var); }; /// Keep track of time range context changes struct TimerangeContext { int time_period; int time_period_offset; bool time_period_seen; int time_sig; int hour; int last_B04024_pos; void init(); void peek_var(const wreport::Var& var, unsigned pos); }; /** * Keep track of the current cloud metadata */ struct CloudContext { Level level; const Level& clcmch(); void init(); void on_vss(const wreport::Subset& subset, unsigned pos); }; struct ContextChooser { const LevelContext& level; const TimerangeContext& trange; // Configuration bool simplified; // Import builder parts const MsgVarShortcut* v; wreport::Var* var; Level chosen_lev; Trange chosen_tr; // Output message Msg* msg; ContextChooser(const LevelContext& level, const TimerangeContext& trange); ~ContextChooser(); void init(Msg& msg, bool simplified); void set_gen_sensor(const wreport::Var& var, wreport::Varcode code, const Level& defaultLevel, const Trange& trange); void set_gen_sensor(const wreport::Var& var, int shortcut); void set_gen_sensor(const wreport::Var& var, int shortcut, const Trange& tr_std, bool tr_careful=false); void set_gen_sensor(const wreport::Var& var, int shortcut, const Level& lev_std, const Trange& tr_std, bool lev_careful=false, bool tr_careful=false); void set_baro_sensor(const wreport::Var& var, int shortcut); void set_past_weather(const wreport::Var& var, int shortcut); void set_wind(const wreport::Var& var, int shortcut); void set_wind_max(const wreport::Var& var, int shortcut); void set_pressure(const wreport::Var& var); void set_water_temperature(const wreport::Var& var); void set_swell_waves(const wreport::Var& var); protected: void ib_start(int shortcut, const wreport::Var& var); Level lev_real(const Level& standard) const; Trange tr_real(const Trange& standard) const; Level lev_shortcut() const { return Level(v->ltype1, v->l1, v->ltype2, v->l2); } Trange tr_shortcut() const { return Trange(v->pind, v->p1, v->p2); } void ib_annotate_level(); void ib_annotate_trange(); void ib_level_use_real(const Level& standard) { chosen_lev = lev_real(standard); } void ib_trange_use_real(const Trange& standard) { chosen_tr = tr_real(standard); } void ib_level_use_shorcut_and_discard_rest() { chosen_lev = lev_shortcut(); } void ib_trange_use_shortcut_and_discard_rest() { chosen_tr = tr_shortcut(); } void ib_level_use_shorcut_and_preserve_rest(const Level& standard); void ib_trange_use_shorcut_and_preserve_rest(const Trange& standard); void ib_level_use_standard_and_preserve_rest(const Level& standard); void ib_trange_use_standard_and_preserve_rest(const Trange& standard); void ib_level_use_shorcut_if_standard_else_real(const Level& standard); void ib_trange_use_shorcut_if_standard_else_real(const Trange& standard); void ib_set(); }; /** * Base class for synop, ship and other importer with synop-like data */ class SynopBaseImporter : public WMOImporter { protected: CloudContext clouds; LevelContext level; TimerangeContext trange; ContextChooser ctx; virtual void peek_var(const wreport::Var& var); virtual void import_var(const wreport::Var& var); public: SynopBaseImporter(const msg::Importer::Options& opts); virtual void init(); virtual void run(); }; } // namespace wr } // namespace msg } // namespace dballe /* vim:set ts=4 sw=4: */ #endif dballe-7.7/dballe/msg/mklevels0000755000175000017500000000665012652630043013324 00000000000000#!/usr/bin/perl -w use strict; use warnings; my $op = $ARGV[0]; sub n($) { return $_[0] if defined $_[0]; return ''; } # Read the data my @items; while () { chop(); my @l = split(/\t+/); # if ($l[0] =~ /^(\d+)-(\d+)$/) # { # for my $i ($1..$2) # { # push @items, [$i, $l[1] or '', $l[2] or '', $l[3] or '']; # } # } # else # { push @items, [$l[0], $l[1], n($l[2])]; # } } # Formatting setup for Doxygen output my ($ltype, $desc, $l1); our $DoxIntro = q{/**@defgroup level_table Level type values @ingroup tables This table lists the possible values for leveltype1 or leveltype2 and the interpretation of the corresponding numerical value l1 or l2. Leveltype values in the range 0-255 can be used for defining either a single level (leveltype1) or a surface delimiting a layer (leveltype1 and leveltype2) with any meaningful combination of leveltypes; values of leveltype >255 have a special use for encoding cloud values in SYNOP reports and they do not strictly define physical surfaces. The idea is borrowed from the GRIB edition 2 fixed surface concept and the values for leveltype coincide with the GRIB standard where possible. \verbatim }; format DoxTop = leveltype Meaning unit/contents of l1/l2 . format Dox = @<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<< $ltype, $desc, $l1, ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<< $desc, $l1, ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<< $desc, $l1, ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<< $desc, $l1, ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<< $desc, $l1, . our $DoxBottom = q{\endverbatim */ }; if ($op eq 'dox') { print $DoxIntro; $^L = "\n\n"; $^ = "DoxTop"; $~ = "Dox"; for my $l (@items) { ($ltype, $desc, $l1) = @$l; write STDOUT; } print $DoxBottom; } elsif ($op eq 'tex') { print q(This table lists the possible values for {\em leveltype1} or {\em leveltype2} and the interpretation of the corresponding numerical value {\em l1} or {\em l2}. Leveltype values in the range 0-255 can be used for defining either a single level (leveltype1) or a surface delimiting a layer (leveltype1 and leveltype2) with any meaningful combination of leveltypes; values of leveltype >255 have a special use for encoding cloud values in SYNOP reports and they do not strictly define physical surfaces. The idea is borrowed from the GRIB edition 2 {\em fixed surface} concept and the values for leveltype coincide with the GRIB standard where possible. \begin{scriptsize} \begin{longtable}{|@{\hspace{0.5mm}}l@{\hspace{0.5mm}}|@{\hspace{0.5mm}}p{4.0cm}@{\hspace{0.5mm}}|@{\hspace{0.5mm}}p{4.0cm}@{\hspace{0.5mm}}|@{\hspace{0.5mm}}p{4.0cm}@{\hspace{0.5mm}}|} \hline {\em leveltype} & {\em Meaning} & {\em unit/contents of l1/l2} \\\\ \hline \endhead \hline \endfoot ); for my $l (@items) { print join(' & ', @$l), "\\\\\n"; } print q(\hline \end{longtable} \end{scriptsize} ); } else { print STDERR "Unknown operation: $op\n"; exit 1; } exit 0; dballe-7.7/dballe/msg/vars.gperf0000644000175000017500000002654712652630120013557 00000000000000 %define slot-name name %define class-name MsgVarLookup %define lookup-function-name find %struct-type %language=C++ %global-table %compare-strncmp /* Using %switch may be faster (remember to check when doing optimizations) */ %{ #include #include #include namespace dballe { %} struct msgvardef { const char* name; int var; }; %% block, DBA_MSG_BLOCK station, DBA_MSG_STATION flight_reg_no, DBA_MSG_FLIGHT_REG_NO ident, DBA_MSG_IDENT st_name, DBA_MSG_ST_NAME st_name_icao, DBA_MSG_ST_NAME_ICAO rep_memo, DBA_MSG_REP_MEMO poll_lcode, DBA_MSG_POLL_LCODE poll_scode, DBA_MSG_POLL_SCODE poll_gemscode, DBA_MSG_POLL_GEMSCODE poll_source, DBA_MSG_POLL_SOURCE poll_atype, DBA_MSG_POLL_ATYPE poll_ttype, DBA_MSG_POLL_TTYPE st_type, DBA_MSG_ST_TYPE wind_inst, DBA_MSG_WIND_INST temp_precision, DBA_MSG_TEMP_PRECISION navsys, DBA_MSG_NAVSYS data_relay, DBA_MSG_DATA_RELAY flight_roll, DBA_MSG_FLIGHT_ROLL latlon_spec, DBA_MSG_LATLON_SPEC year, DBA_MSG_YEAR month, DBA_MSG_MONTH day, DBA_MSG_DAY hour, DBA_MSG_HOUR minute, DBA_MSG_MINUTE second, DBA_MSG_SECOND latitude, DBA_MSG_LATITUDE longitude, DBA_MSG_LONGITUDE isobaric_surface, DBA_MSG_ISOBARIC_SURFACE height_release, DBA_MSG_HEIGHT_RELEASE height_station, DBA_MSG_HEIGHT_STATION height_baro, DBA_MSG_HEIGHT_BARO flight_phase, DBA_MSG_FLIGHT_PHASE timesig, DBA_MSG_TIMESIG station_height_quality, DBA_MSG_STATION_HEIGHT_QUALITY cloud_n, DBA_MSG_CLOUD_N cloud_n4, DBA_MSG_CLOUD_N4 cloud_c4, DBA_MSG_CLOUD_C4 cloud_h4, DBA_MSG_CLOUD_H4 cloud_n3, DBA_MSG_CLOUD_N3 cloud_c3, DBA_MSG_CLOUD_C3 cloud_h3, DBA_MSG_CLOUD_H3 cloud_n2, DBA_MSG_CLOUD_N2 cloud_c2, DBA_MSG_CLOUD_C2 cloud_h2, DBA_MSG_CLOUD_H2 cloud_n1, DBA_MSG_CLOUD_N1 cloud_c1, DBA_MSG_CLOUD_C1 cloud_h1, DBA_MSG_CLOUD_H1 cloud_ch, DBA_MSG_CLOUD_CH cloud_cm, DBA_MSG_CLOUD_CM cloud_cl, DBA_MSG_CLOUD_CL cloud_nh, DBA_MSG_CLOUD_NH cloud_hh, DBA_MSG_CLOUD_HH wind_dir, DBA_MSG_WIND_DIR wind_speed, DBA_MSG_WIND_SPEED ex_ccw_wind, DBA_MSG_EX_CCW_WIND ex_cw_wind, DBA_MSG_EX_CW_WIND wind_gust_max_speed, DBA_MSG_WIND_GUST_MAX_SPEED wind_gust_max_dir, DBA_MSG_WIND_GUST_MAX_DIR qnh, DBA_MSG_QNH temp_2m, DBA_MSG_TEMP_2M wet_temp_2m, DBA_MSG_WET_TEMP_2M dewpoint_2m, DBA_MSG_DEWPOINT_2M humidity, DBA_MSG_HUMIDITY press_msl, DBA_MSG_PRESS_MSL st_dir, DBA_MSG_ST_DIR st_speed, DBA_MSG_ST_SPEED meas_equip_type, DBA_MSG_MEAS_EQUIP_TYPE sonde_type, DBA_MSG_SONDE_TYPE sonde_method, DBA_MSG_SONDE_METHOD sonde_correction, DBA_MSG_SONDE_CORRECTION sonde_tracking, DBA_MSG_SONDE_TRACKING press, DBA_MSG_PRESS height_anem, DBA_MSG_HEIGHT_ANEM tot_snow, DBA_MSG_TOT_SNOW visibility, DBA_MSG_VISIBILITY pres_wtr, DBA_MSG_PRES_WTR metar_wtr, DBA_MSG_METAR_WTR state_ground, DBA_MSG_STATE_GROUND water_temp, DBA_MSG_WATER_TEMP past_wtr1_6h, DBA_MSG_PAST_WTR1_6H past_wtr2_6h, DBA_MSG_PAST_WTR2_6H press_tend, DBA_MSG_PRESS_TEND past_wtr1_3h, DBA_MSG_PAST_WTR1_3H past_wtr2_3h, DBA_MSG_PAST_WTR2_3H press_24h, DBA_MSG_PRESS_24H press_3h, DBA_MSG_PRESS_3H tot_prec24, DBA_MSG_TOT_PREC24 tot_prec12, DBA_MSG_TOT_PREC12 tot_prec6, DBA_MSG_TOT_PREC6 tot_prec3, DBA_MSG_TOT_PREC3 tot_prec1, DBA_MSG_TOT_PREC1 %% int resolve_var(const char* name) { struct msgvardef* res = MsgVarLookup::find(name, strlen(name)); if (res == NULL) return -1; else return res->var; } int resolve_var_substring(const char* name, int len) { struct msgvardef* res = MsgVarLookup::find(name, len); if (res == NULL) return -1; else return res->var; } struct MsgVarShortcut shortcutTable[] = { { WR_VAR(0, 1, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 2), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 8), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 11), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 19), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 63), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 194), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 212), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 213), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 214), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 215), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 216), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 1, 217), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 2), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 5), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 61), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 62), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 63), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 2, 70), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 2), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 3), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 4), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 5), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 4, 6), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 5, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 6, 1), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 7, 4), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 7, 7), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 7, 30), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 7, 31), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 8, 4), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 8, 21), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 33, 24), MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT, MISSING_INT }, { WR_VAR(0, 20, 10), 256, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 259, 4, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 259, 4, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 259, 4, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 259, 3, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 259, 3, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 259, 3, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 259, 2, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 259, 2, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 259, 2, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 259, 1, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 259, 1, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 259, 1, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 258, 3, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 258, 2, 254, 0, 0 }, { WR_VAR(0, 20, 12), 256, MISSING_INT, 258, 1, 254, 0, 0 }, { WR_VAR(0, 20, 11), 256, MISSING_INT, 258, 0, 254, 0, 0 }, { WR_VAR(0, 20, 13), 256, MISSING_INT, 258, 0, 254, 0, 0 }, { WR_VAR(0, 11, 1), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 2), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 16), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 17), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 41), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 11, 43), 103, 10000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 10, 52), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 12, 101), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 12, 102), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 12, 103), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 13, 3), 103, 2000, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 10, 51), 101, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 1, 12), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 1, 13), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 3), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 12), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 13), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 2, 14), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 10, 4), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 10, 197), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 13, 13), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 1), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 3), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 9), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 62), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 22, 43), 1, MISSING_INT, MISSING_INT, MISSING_INT, 254, 0, 0 }, { WR_VAR(0, 20, 4), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 21600 }, { WR_VAR(0, 20, 5), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 21600 }, { WR_VAR(0, 10, 63), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 10800 }, { WR_VAR(0, 20, 4), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 10800 }, { WR_VAR(0, 20, 5), 1, MISSING_INT, MISSING_INT, MISSING_INT, 205, 0, 10800 }, { WR_VAR(0, 10, 60), 1, MISSING_INT, MISSING_INT, MISSING_INT, 4, 0, 86400 }, { WR_VAR(0, 10, 60), 1, MISSING_INT, MISSING_INT, MISSING_INT, 4, 0, 10800 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 86400 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 43200 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 21600 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 10800 }, { WR_VAR(0, 13, 11), 1, MISSING_INT, MISSING_INT, MISSING_INT, 1, 0, 3600 }, }; } // namespace dballe dballe-7.7/dballe/msg/codec.h0000644000175000017500000000773112652630043013003 00000000000000#ifndef DBA_MSG_CODEC_H #define DBA_MSG_CODEC_H #include #include #include #include #include /** @file * @ingroup msg * General codec options */ namespace wreport { struct Bulletin; } namespace dballe { struct Messages; struct Message; namespace msg { /** * Message importer * * This class is designed like a configurable virtual functor. * * Importers of various kinds can provide their implementations. */ class Importer { public: struct Options { bool simplified; /// Create new Options initialised with default values Options() : simplified(true) {} bool operator==(const Options& o) const { return simplified == o.simplified; } bool operator!=(const Options& o) const { return simplified != o.simplified; } /// Print a summary of the options to \a out void print(FILE* out); /// Generate a string summary of import options std::string to_string() const; /// Opposite of to_string: create an Options from a string static Options from_string(const std::string& s); }; protected: Options opts; public: Importer(const Options& opts); virtual ~Importer(); /** * Decode a message from its raw encoded representation * * @param rmsg * Encoded message * @retval msgs * The resulting ::dba_msg */ Messages from_binary(const BinaryMessage& msg) const; /** * Decode a message from its raw encoded representation, calling \a dest on * each resulting Message. * * Return false from \a dest to stop decoding. * * @param rmsg * Encoded message. * @retval dest * The function that consumes the decoded messages. * @returns true if it got to the end of decoding, false if dest returned false. */ virtual bool foreach_decoded(const BinaryMessage& msg, std::function&&)> dest) const = 0; /** * Import a decoded BUFR/CREX message */ virtual Messages from_bulletin(const wreport::Bulletin& msg) const = 0; /// Instantiate the right importer for the given type static std::unique_ptr create(File::Encoding type, const Options& opts=Options()); }; /** * Message exporter * * This class is designed like a configurable virtual functor. * * Exporters of various kinds can provide their implementations. */ class Exporter { public: struct Options { /// Name of template to use for output (leave empty to autodetect) std::string template_name; /// Originating centre int centre; /// Originating subcentre int subcentre; /// Originating application ID int application; /// Create new Options initialised with default values Options() : centre(MISSING_INT), subcentre(MISSING_INT), application(MISSING_INT) {} /// Print a summary of the options to \a out void print(FILE* out); /// Generate a string summary of export options std::string to_string() const; }; protected: Options opts; public: Exporter(const Options& opts); virtual ~Exporter(); /** * Encode a message * * @param msgs * Message to encode * @retval rmsg * The resulting BinaryMessage */ virtual std::string to_binary(const Messages& msgs) const = 0; /** * Export to a Bulletin */ virtual std::unique_ptr to_bulletin(const Messages& msgs) const = 0; /** * Create a bulletin that works with this exporter. * * @returns the bulletin, or NULL of this is an exporter for a format not * covered by Bulletin */ virtual std::unique_ptr make_bulletin() const; /// Instantiate the right importer for the given type static std::unique_ptr create(File::Encoding type, const Options& opts=Options()); }; } } #endif dballe-7.7/dballe/msg/wr_exporters/0000755000175000017500000000000012653425050014371 500000000000000dballe-7.7/dballe/msg/wr_exporters/temp.cc0000644000175000017500000010750212652630043015571 00000000000000/* * Copyright (C) 2005--2015 ARPA-SIM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Enrico Zini */ #include "msg/wr_codec.h" #include "msg/msg.h" #include "msg/context.h" #include #include #include #include #include using namespace wreport; using namespace std; #define TEMP_WMO_NAME "temp-wmo" #define TEMP_WMO_DESC "Temp WMO (2.101)" #define TEMP_ECMWF_LAND_NAME "temp-ecmwf-land" #define TEMP_ECMWF_LAND_DESC "Temp ECMWF land (2.101)" #define TEMP_ECMWF_SHIP_NAME "temp-ecmwf-ship" #define TEMP_ECMWF_SHIP_DESC "Temp ECMWF ship (2.102)" #define TEMP_RADAR_NAME "temp-radar" #define TEMP_RADAR_DESC "Temp radar doppler wind profile (6.1)" #define PILOT_WMO_NAME "pilot-wmo" #define PILOT_WMO_DESC "Pilot (2.1, 2.2, 2.3)" #define PILOT_ECMWF_NAME "pilot-ecmwf" #define PILOT_ECMWF_DESC "Pilot (2.91)" namespace dballe { namespace msg { namespace wr { namespace { // Base template for vertical soundings struct TempBase : public Template { bool is_crex; TempBase(const Exporter::Options& opts, const Messages& msgs) : Template(opts, msgs) {} /// Count the number of sounding levels int count_levels() const { int lev_no = 0; for (size_t i = 0; i < msg->data.size(); ++i) { if (msg->data[i]->find_vsig() != NULL) ++lev_no; } return lev_no; } int add_sounding_levels() { int count = count_levels(); subset->store_variable_i(WR_VAR(0, 31, 1), count); // Iterate backwards as we need to add levels in decreasing pressure order for (int i = msg->data.size() - 1; i >= 0; --i) { msg::Context& c = *msg->data[i]; // We only want levels with a vertical sounding significance const Var* vss = c.find_vsig(); if (vss == NULL) continue; /* We only want pressure levels */ if (c.level.ltype1 != 100) continue; double press = c.level.l1; /* Add pressure */ const Var* press_var = c.find(WR_VAR(0, 10, 4)); if (!press_var) press_var = c.find(WR_VAR(0, 7, 4)); if (press_var) subset->store_variable(WR_VAR(0, 7, 4), *press_var); else if (press == MISSING_INT) subset->store_variable_undef(WR_VAR(0, 7, 4)); else subset->store_variable_d(WR_VAR(0, 7, 4), press); /* Add vertical sounding significance */ { int vssval = convert_BUFR08042_to_BUFR08001(vss->enqi()); if (vssval & BUFR08042::MISSING) { // Deal with 'missing VSS' group markers subset->store_variable_undef(WR_VAR(0, 8, 1)); } else { Var nvar(subset->tables->btable->query(WR_VAR(0, 8, 1)), vssval); nvar.setattrs(*vss); subset->store_variable(WR_VAR(0, 8, 1), nvar); } } /* Add the rest */ add(WR_VAR(0, 10, 3), &c, WR_VAR(0, 10, 8)); add(WR_VAR(0, 12, 1), &c, WR_VAR(0, 12, 101)); add(WR_VAR(0, 12, 3), &c, WR_VAR(0, 12, 103)); add(WR_VAR(0, 11, 1), &c, WR_VAR(0, 11, 1)); add(WR_VAR(0, 11, 2), &c, WR_VAR(0, 11, 2)); } return count; } virtual void setupBulletin(wreport::Bulletin& bulletin) { Template::setupBulletin(bulletin); // Use old table for old templates if (BufrBulletin* b = dynamic_cast(&bulletin)) { b->master_table_version_number = 13; } is_crex = dynamic_cast(&bulletin) != 0; bulletin.data_category = 2; bulletin.data_subcategory = 255; // Scan to see what we are dealing with bulletin.data_subcategory_local = 101; for (const auto& mi: msgs) { const Msg& msg = Msg::downcast(mi); if (msg.type == MSG_PILOT) { bulletin.data_subcategory_local = 91; break; } else if (msg.get_ident_var()) { bulletin.data_subcategory_local = 102; break; } else if (msg.get_block_var()) { break; } } } virtual void to_subset(const Msg& msg, wreport::Subset& subset) { Template::to_subset(msg, subset); } bool do_D03051(const msg::Context& c) { add(WR_VAR(0, 4, 86), &c); add(WR_VAR(0, 8, 42), &c); if (c.level.l1 == MISSING_INT) subset->store_variable_undef(WR_VAR(0, 7, 4)); else subset->store_variable_d(WR_VAR(0, 7, 4), c.level.l1); add(WR_VAR(0, 5, 15), &c); add(WR_VAR(0, 6, 15), &c); add(WR_VAR(0, 11, 61), &c); add(WR_VAR(0, 11, 62), &c); return true; } bool do_D03053(const msg::Context& c) { add(WR_VAR(0, 4, 86), &c); add(WR_VAR(0, 8, 42), &c); if (c.level.l1 == MISSING_INT) subset->store_variable_undef(WR_VAR(0, 7, 9)); else subset->store_variable_d(WR_VAR(0, 7, 9), c.level.l1); add(WR_VAR(0, 5, 15), &c); add(WR_VAR(0, 6, 15), &c); add(WR_VAR(0, 11, 61), &c); add(WR_VAR(0, 11, 62), &c); return true; } }; struct TempWMO : public TempBase { TempWMO(const Exporter::Options& opts, const Messages& msgs) : TempBase(opts, msgs) {} virtual const char* name() const { return TEMP_WMO_NAME; } virtual const char* description() const { return TEMP_WMO_DESC; } virtual void setupBulletin(wreport::Bulletin& bulletin) { TempBase::setupBulletin(bulletin); bulletin.data_category = 2; bulletin.data_subcategory = 4; bulletin.data_subcategory_local = 255; for (const auto& mi : msgs) { const Msg& msg = Msg::downcast(mi); if (msg.type == MSG_TEMP_SHIP) { bulletin.data_subcategory = 5; break; } } // Data descriptor section bulletin.datadesc.clear(); bulletin.datadesc.push_back(WR_VAR(3, 9, 52)); bulletin.load_tables(); } void do_D03054(const msg::Context& c) { add(WR_VAR(0, 4, 86), &c); if (const Var* vss = c.find(WR_VAR(0, 8, 42))) { // Deal with 'missing VSS' group markers if (vss->enq((int)BUFR08042::MISSING) & BUFR08042::MISSING) subset->store_variable_undef(WR_VAR(0, 8, 42)); else subset->store_variable(*vss); } else subset->store_variable_undef(WR_VAR(0, 8, 42)); switch (c.level.ltype1) { case 100: if (c.level.l1 == MISSING_INT) subset->store_variable_undef(WR_VAR(0, 7, 4)); else subset->store_variable_d(WR_VAR(0, 7, 4), c.level.l1); add(WR_VAR(0, 10, 9), &c, WR_VAR(0, 10, 8)); break; case 102: add(WR_VAR(0, 7, 4), &c, WR_VAR(0, 10, 4)); if (const Var* var = c.find(WR_VAR(0, 10, 8))) add(WR_VAR(0, 10, 9), var); else subset->store_variable_d(WR_VAR(0, 10, 9), (double)c.level.l1); break; case 103: add(WR_VAR(0, 7, 4), &c, WR_VAR(0, 10, 4)); add(WR_VAR(0, 10, 9), &c, WR_VAR(0, 10, 8)); break; } add(WR_VAR(0, 5, 15), &c); add(WR_VAR(0, 6, 15), &c); add(WR_VAR(0, 12, 101), &c); add(WR_VAR(0, 12, 103), &c); add(WR_VAR(0, 11, 1), &c); add(WR_VAR(0, 11, 2), &c); } virtual void to_subset(const Msg& msg, wreport::Subset& subset) { TempBase::to_subset(msg, subset); do_D01001(); // station id add(WR_VAR(0, 1, 11), c_station, DBA_MSG_IDENT); add(WR_VAR(0, 2, 11), c_gnd_instant, DBA_MSG_SONDE_TYPE); add(WR_VAR(0, 2, 13), c_gnd_instant, DBA_MSG_SONDE_CORRECTION); add(WR_VAR(0, 2, 14), c_gnd_instant, DBA_MSG_SONDE_TRACKING); add(WR_VAR(0, 2, 3), c_gnd_instant, DBA_MSG_MEAS_EQUIP_TYPE); subset.store_variable_i(WR_VAR(0, 8, 21), 18); do_D01011(); // date do_D01013(); // time do_D01021(); // coordinates add(WR_VAR(0, 7, 30), c_station, DBA_MSG_HEIGHT_STATION); add(WR_VAR(0, 7, 31), c_station, DBA_MSG_HEIGHT_BARO); add(WR_VAR(0, 7, 7), c_station, DBA_MSG_HEIGHT_RELEASE); add(WR_VAR(0, 33, 24), c_station, DBA_MSG_STATION_HEIGHT_QUALITY); // Cloud information reported with vertical soundings add(WR_VAR(0, 8, 2), WR_VAR(0, 8, 2), Level::cloud(258, 0), Trange::instant()); add(WR_VAR(0, 20, 11), DBA_MSG_CLOUD_NH); add(WR_VAR(0, 20, 13), DBA_MSG_CLOUD_HH); add(WR_VAR(0, 20, 12), DBA_MSG_CLOUD_CL); add(WR_VAR(0, 20, 12), DBA_MSG_CLOUD_CM); add(WR_VAR(0, 20, 12), DBA_MSG_CLOUD_CH); subset.store_variable_undef(WR_VAR(0, 8, 2)); add(WR_VAR(0, 22, 43), c_gnd_instant, DBA_MSG_WATER_TEMP); // Undef for now, we fill it later size_t rep_count_pos = subset.size(); subset.store_variable_undef(WR_VAR(0, 31, 2)); // Temperature, dew-point and wind data at pressure levels int group_count = 0; for (std::vector::const_reverse_iterator i = msg.data.rbegin(); i != msg.data.rend(); ++i) { // Iterate backwards to get pressure levels sorted from the higher // to the lower pressure const msg::Context* c = *i; // Skip non-presure levels if (!c->find_vsig()) continue; // Skip levels not for us if (!( c->find(WR_VAR(0, 10, 8)) || c->find(WR_VAR(0, 12, 101)) || c->find(WR_VAR(0, 12, 103)) || c->find(WR_VAR(0, 11, 1)) || c->find(WR_VAR(0, 11, 2))) && ( c->find(WR_VAR(0, 11, 61)) || c->find(WR_VAR(0, 11, 62))) ) continue; do_D03054(*c); ++group_count; } subset[rep_count_pos].seti(group_count); // Wind shear data rep_count_pos = subset.size(); subset.store_variable_undef(WR_VAR(0, 31, 1)); group_count = 0; for (std::vector::const_reverse_iterator i = msg.data.rbegin(); i != msg.data.rend(); ++i) { // Iterate backwards to get pressure levels sorted from the higher // to the lower pressure const msg::Context* c = *i; // Skip non-pressure levels if (c->level.ltype1 != 100) continue; // Skip levels not for us if (!( c->find(WR_VAR(0, 11, 61)) || c->find(WR_VAR(0, 11, 62)))) continue; if (do_D03051(*c)) ++group_count; } subset[rep_count_pos].seti(group_count); } }; struct TempRadar : public TempBase { TempRadar(const Exporter::Options& opts, const Messages& msgs) : TempBase(opts, msgs) {} virtual const char* name() const { return TEMP_RADAR_NAME; } virtual const char* description() const { return TEMP_RADAR_DESC; } virtual void setupBulletin(wreport::Bulletin& bulletin) { TempBase::setupBulletin(bulletin); bulletin.data_category = 6; bulletin.data_subcategory = 1; bulletin.data_subcategory_local = 255; // Data descriptor section bulletin.datadesc.clear(); bulletin.datadesc.push_back(WR_VAR(0, 1, 33)); bulletin.datadesc.push_back(WR_VAR(0, 1, 34)); bulletin.datadesc.push_back(WR_VAR(3, 1, 1)); bulletin.datadesc.push_back(WR_VAR(3, 1, 11)); bulletin.datadesc.push_back(WR_VAR(3, 1, 12)); bulletin.datadesc.push_back(WR_VAR(3, 1, 22)); bulletin.datadesc.push_back(WR_VAR(0, 2, 3)); bulletin.datadesc.push_back(WR_VAR(0, 2, 121)); bulletin.datadesc.push_back(WR_VAR(0, 2, 125)); bulletin.datadesc.push_back(WR_VAR(1, 7, 0)); bulletin.datadesc.push_back(WR_VAR(0, 31, 1)); bulletin.datadesc.push_back(WR_VAR(0, 7, 7)); bulletin.datadesc.push_back(WR_VAR(0, 11, 1)); bulletin.datadesc.push_back(WR_VAR(0, 11, 2)); bulletin.datadesc.push_back(WR_VAR(0, 33, 2)); bulletin.datadesc.push_back(WR_VAR(0, 11, 6)); bulletin.datadesc.push_back(WR_VAR(0, 33, 2)); bulletin.datadesc.push_back(WR_VAR(0, 11, 50)); bulletin.load_tables(); } virtual void to_subset(const Msg& msg, wreport::Subset& subset) { TempBase::to_subset(msg, subset); add(WR_VAR(0, 1, 33), c_station); add(WR_VAR(0, 1, 34), c_station); do_D01001(); // station id do_D01011(); // date do_D01012(); // date do_D01022(); // date add(WR_VAR(0, 2, 3), c_gnd_instant, DBA_MSG_MEAS_EQUIP_TYPE); add(WR_VAR(0, 2, 121), c_gnd_instant); add(WR_VAR(0, 2, 125), c_gnd_instant); // Undef for now, we fill it later size_t rep_count_pos = subset.size(); subset.store_variable_undef(WR_VAR(0, 31, 1)); // Sounding levels int group_count = 0; for (std::vector::const_reverse_iterator i = msg.data.rbegin(); i != msg.data.rend(); ++i) { // Iterate backwards to get pressure levels sorted from the higher // to the lower pressure const msg::Context* c = *i; // We are only interested in height levels if (c->level.ltype1 != 102) continue; if (const Var* var = c->find(WR_VAR(0, 7, 7))) add(WR_VAR(0, 7, 7), var); else subset.store_variable_d(WR_VAR(0, 7, 7), c->level.l1/1000.0); add(WR_VAR(0, 11, 1), c); static const Varcode codes[] = { WR_VAR(0, 11, 2), WR_VAR(0, 11, 6) }; for (unsigned i = 0; i < 2; ++i) { Varcode code = codes[i]; if (const wreport::Var *var = c->find(code)) { add(code, var); add(WR_VAR(0, 33, 2), var->enqa(WR_VAR(0, 33, 2))); } else { subset.store_variable_undef(code); subset.store_variable_undef(WR_VAR(0, 33, 2)); } } add(WR_VAR(0, 11, 50), c); ++group_count; } subset[rep_count_pos].seti(group_count); } }; struct TempEcmwfLand : public TempBase { TempEcmwfLand(const Exporter::Options& opts, const Messages& msgs) : TempBase(opts, msgs) {} virtual const char* name() const { return TEMP_ECMWF_LAND_NAME; } virtual const char* description() const { return TEMP_ECMWF_LAND_DESC; } virtual void setupBulletin(wreport::Bulletin& bulletin) { TempBase::setupBulletin(bulletin); // Data descriptor section bulletin.datadesc.clear(); bulletin.datadesc.push_back(WR_VAR(3, 9, 7)); if (!is_crex) { bulletin.datadesc.push_back(WR_VAR(2, 22, 0)); bulletin.datadesc.push_back(WR_VAR(1, 1, 0)); bulletin.datadesc.push_back(WR_VAR(0, 31, 2)); bulletin.datadesc.push_back(WR_VAR(0, 31, 31)); bulletin.datadesc.push_back(WR_VAR(0, 1, 31)); bulletin.datadesc.push_back(WR_VAR(0, 1, 32)); bulletin.datadesc.push_back(WR_VAR(1, 1, 0)); bulletin.datadesc.push_back(WR_VAR(0, 31, 2)); bulletin.datadesc.push_back(WR_VAR(0, 33, 7)); } bulletin.load_tables(); } virtual void to_subset(const Msg& msg, wreport::Subset& subset) { TempBase::to_subset(msg, subset); /* 0 */ add(WR_VAR(0, 1, 1), DBA_MSG_BLOCK); /* 1 */ add(WR_VAR(0, 1, 2), DBA_MSG_STATION); /* 2 */ add(WR_VAR(0, 2, 11), DBA_MSG_SONDE_TYPE); /* 3 */ add(WR_VAR(0, 2, 12), DBA_MSG_SONDE_METHOD); do_D01011(); do_D01012(); /* 9 */ add(WR_VAR(0, 5, 1), DBA_MSG_LATITUDE); /* 10 */ add(WR_VAR(0, 6, 1), DBA_MSG_LONGITUDE); /* 11 */ add(WR_VAR(0, 7, 1), DBA_MSG_HEIGHT_STATION); /* 12 */ add(WR_VAR(0, 20, 10), DBA_MSG_CLOUD_N); /* 13 */ add(WR_VAR(0, 8, 2), WR_VAR(0, 8, 2), Level::cloud(258, 0), Trange::instant()); /* 14 */ add(WR_VAR(0, 20, 11), DBA_MSG_CLOUD_NH); /* 15 */ add(WR_VAR(0, 20, 13), DBA_MSG_CLOUD_HH); /* 16 */ add(WR_VAR(0, 20, 12), DBA_MSG_CLOUD_CL); /* 17 */ add(WR_VAR(0, 20, 12), DBA_MSG_CLOUD_CM); /* 18 */ add(WR_VAR(0, 20, 12), DBA_MSG_CLOUD_CH); add_sounding_levels(); if (!is_crex) { int count = subset.append_dpb(WR_VAR(2, 22, 0), subset.size(), WR_VAR(0, 33, 7)); if (opts.centre != MISSING_INT) subset.store_variable_i(WR_VAR(0, 1, 31), opts.centre); else subset.store_variable_undef(WR_VAR(0, 1, 31)); if (opts.application != MISSING_INT) subset.store_variable_i(WR_VAR(0, 1, 32), opts.application); else subset.store_variable_undef(WR_VAR(0, 1, 32)); subset.store_variable_i(WR_VAR(0, 31, 2), count); } } }; struct TempEcmwfShip : public TempBase { TempEcmwfShip(const Exporter::Options& opts, const Messages& msgs) : TempBase(opts, msgs) {} virtual const char* name() const { return TEMP_ECMWF_SHIP_NAME; } virtual const char* description() const { return TEMP_ECMWF_SHIP_DESC; } virtual void setupBulletin(wreport::Bulletin& bulletin) { TempBase::setupBulletin(bulletin); // Data descriptor section bulletin.datadesc.clear(); /* FIXME: some expansions are not in CREX D tables yet, so we need to use * the expanded version here. The code needs to be changed when newer CREX * D tables are available */ /* WR_VAR(3, 9, 196), Replaced with expansion: */ bulletin.datadesc.push_back(WR_VAR(3, 1, 3)); bulletin.datadesc.push_back(WR_VAR(0, 2, 11)); bulletin.datadesc.push_back(WR_VAR(0, 2, 12)); bulletin.datadesc.push_back(WR_VAR(3, 1, 11)); bulletin.datadesc.push_back(WR_VAR(3, 1, 12)); bulletin.datadesc.push_back(WR_VAR(3, 1, 23)); bulletin.datadesc.push_back(WR_VAR(0, 7, 1)); bulletin.datadesc.push_back(WR_VAR(3, 2, 4)); bulletin.datadesc.push_back(WR_VAR(1, 1, 0)); bulletin.datadesc.push_back(WR_VAR(0, 31, 1)); bulletin.datadesc.push_back(WR_VAR(3, 3, 14)); if (!is_crex) { bulletin.datadesc.push_back(WR_VAR(2, 22, 0)); bulletin.datadesc.push_back(WR_VAR(1, 1, 0)); bulletin.datadesc.push_back(WR_VAR(0, 31, 2)); bulletin.datadesc.push_back(WR_VAR(0, 31, 31)); bulletin.datadesc.push_back(WR_VAR(0, 1, 31)); bulletin.datadesc.push_back(WR_VAR(0, 1, 32)); bulletin.datadesc.push_back(WR_VAR(1, 1, 0)); bulletin.datadesc.push_back(WR_VAR(0, 31, 2)); bulletin.datadesc.push_back(WR_VAR(0, 33, 7)); } bulletin.load_tables(); } virtual void to_subset(const Msg& msg, wreport::Subset& subset) { TempBase::to_subset(msg, subset); /* 0 */ add(WR_VAR(0, 1, 11), DBA_MSG_IDENT); /* 1 */ add(WR_VAR(0, 1, 12), DBA_MSG_ST_DIR); /* 2 */ add(WR_VAR(0, 1, 13), DBA_MSG_ST_SPEED); /* 3 */ add(WR_VAR(0, 2, 11), DBA_MSG_SONDE_TYPE); /* 4 */ add(WR_VAR(0, 2, 12), DBA_MSG_SONDE_METHOD); do_D01011(); do_D01012(); /* 10 */ add(WR_VAR(0, 5, 2), DBA_MSG_LATITUDE); /* 11 */ add(WR_VAR(0, 6, 2), DBA_MSG_LONGITUDE); /* 12 */ add(WR_VAR(0, 7, 1), DBA_MSG_HEIGHT_STATION); /* 13 */ add(WR_VAR(0, 20, 10), DBA_MSG_CLOUD_N); /* 14 */ add(WR_VAR(0, 8, 2), WR_VAR(0, 8, 2), Level::cloud(258, 0), Trange::instant()); /* 15 */ add(WR_VAR(0, 20, 11), DBA_MSG_CLOUD_NH); /* 16 */ add(WR_VAR(0, 20, 13), DBA_MSG_CLOUD_HH); /* 17 */ add(WR_VAR(0, 20, 12), DBA_MSG_CLOUD_CL); /* 18 */ add(WR_VAR(0, 20, 12), DBA_MSG_CLOUD_CM); /* 19 */ add(WR_VAR(0, 20, 12), DBA_MSG_CLOUD_CH); add_sounding_levels(); if (!is_crex) { int count = subset.append_dpb(WR_VAR(2, 22, 0), subset.size(), WR_VAR(0, 33, 7)); if (opts.centre != MISSING_INT) subset.store_variable_i(WR_VAR(0, 1, 31), opts.centre); else subset.store_variable_undef(WR_VAR(0, 1, 31)); if (opts.application != MISSING_INT) subset.store_variable_i(WR_VAR(0, 1, 32), opts.application); else subset.store_variable_undef(WR_VAR(0, 1, 32)); subset.store_variable_i(WR_VAR(0, 31, 2), count); } } }; struct PilotWMO : public TempBase { bool pressure_levs; PilotWMO(const Exporter::Options& opts, const Messages& msgs) : TempBase(opts, msgs) {} virtual const char* name() const { return PILOT_WMO_NAME; } virtual const char* description() const { return PILOT_WMO_DESC; } virtual void to_bulletin(wreport::Bulletin& bulletin) { // Scan contexts to see if we are encoding pressure or height levels unsigned has_press = 0; unsigned has_height = 0; for (const auto& mi: msgs) { const Msg& msg = Msg::downcast(mi); for (std::vector::const_iterator i = msg.data.begin(); i != msg.data.end(); ++i) { switch ((*i)->level.ltype1) { case 100: ++has_press; break; case 102: ++has_height; break; case 103: ++has_height; break; } } } pressure_levs = has_press >= has_height; // Continue with normal operations TempBase::to_bulletin(bulletin); } virtual void setupBulletin(wreport::Bulletin& bulletin) { TempBase::setupBulletin(bulletin); bulletin.data_category = 2; bulletin.data_subcategory = 1; bulletin.data_subcategory_local = 255; // Data descriptor section bulletin.datadesc.clear(); if (pressure_levs) bulletin.datadesc.push_back(WR_VAR(3, 9, 50)); // For pressure levels else bulletin.datadesc.push_back(WR_VAR(3, 9, 51)); // For height levels bulletin.load_tables(); } virtual void to_subset(const Msg& msg, wreport::Subset& subset) { TempBase::to_subset(msg, subset); // Identification of launch site and instrumentation add(WR_VAR(0, 1, 1), DBA_MSG_BLOCK); add(WR_VAR(0, 1, 2), DBA_MSG_STATION); add(WR_VAR(0, 1, 11), DBA_MSG_IDENT); add(WR_VAR(0, 2, 11), DBA_MSG_SONDE_TYPE); add(WR_VAR(0, 2, 14), DBA_MSG_SONDE_TRACKING); add(WR_VAR(0, 2, 3), DBA_MSG_MEAS_EQUIP_TYPE); // Date/time of launch add(WR_VAR(0, 8, 21), 18); // Launch time do_D01011(); do_D01013(); // Horizontal and vertical coordinates of launch site add(WR_VAR(0, 5, 1), DBA_MSG_LATITUDE); add(WR_VAR(0, 6, 1), DBA_MSG_LONGITUDE); add(WR_VAR(0, 7, 30), DBA_MSG_HEIGHT_STATION); add(WR_VAR(0, 7, 31), DBA_MSG_HEIGHT_BARO); add(WR_VAR(0, 7, 7), DBA_MSG_HEIGHT_RELEASE); add(WR_VAR(0, 33, 24), DBA_MSG_STATION_HEIGHT_QUALITY); // Keep track of where we stored int rep_count_pos = subset.size(); subset.store_variable_undef(WR_VAR(0, 31, 2)); /* Iterate backwards as we need to add levels in decreasing pressure order */ int group_count = 0; for (std::vector::const_reverse_iterator i = msg.data.rbegin(); i != msg.data.rend(); ++i) { const msg::Context& c = **i; // We only want levels with a vertical sounding significance const Var* vss = c.find_vsig(); if (vss == NULL) continue; if (pressure_levs && c.level.ltype1 != 100) continue; if (!pressure_levs && c.level.ltype1 != 102) continue; add(WR_VAR(0, 4, 86), &c); add(WR_VAR(0, 8, 42), &c); if (pressure_levs) { // Wind data at pressure levels if (c.level.l1 == MISSING_INT) subset.store_variable_undef(WR_VAR(0, 7, 4)); else subset.store_variable_d(WR_VAR(0, 7, 4), c.level.l1); } else { // Wind data at heights if (c.level.l1 == MISSING_INT) subset.store_variable_undef(WR_VAR(0, 7, 9)); else subset.store_variable_d(WR_VAR(0, 7, 9), c.level.l1); } add(WR_VAR(0, 5, 15), &c); add(WR_VAR(0, 6, 15), &c); add(WR_VAR(0, 11, 1), &c); add(WR_VAR(0, 11, 2), &c); ++group_count; } subset[rep_count_pos].seti(group_count); // Wind shear data rep_count_pos = subset.size(); subset.store_variable_undef(WR_VAR(0, 31, 1)); group_count = 0; for (std::vector::const_reverse_iterator i = msg.data.rbegin(); i != msg.data.rend(); ++i) { // Iterate backwards to get pressure levels sorted from the higher // to the lower pressure const msg::Context& c = **i; // Skip levels that do not fit if (pressure_levs && c.level.ltype1 != 100) continue; if (!pressure_levs && c.level.ltype1 != 102) continue; if (pressure_levs) { if (do_D03051(c)) ++group_count; } else { if (do_D03053(c)) ++group_count; } } subset[rep_count_pos].seti(group_count); } }; struct PilotEcmwf : public TempBase { PilotEcmwf(const Exporter::Options& opts, const Messages& msgs) : TempBase(opts, msgs) {} virtual const char* name() const { return PILOT_ECMWF_NAME; } virtual const char* description() const { return PILOT_ECMWF_DESC; } virtual void setupBulletin(wreport::Bulletin& bulletin) { TempBase::setupBulletin(bulletin); // Data descriptor section bulletin.datadesc.clear(); bulletin.datadesc.push_back(WR_VAR(3, 1, 1)); bulletin.datadesc.push_back(WR_VAR(0, 2, 11)); bulletin.datadesc.push_back(WR_VAR(0, 2, 12)); bulletin.datadesc.push_back(WR_VAR(3, 1, 11)); bulletin.datadesc.push_back(WR_VAR(3, 1, 12)); bulletin.datadesc.push_back(WR_VAR(3, 1, 22)); bulletin.datadesc.push_back(WR_VAR(1, 5, 0)); bulletin.datadesc.push_back(WR_VAR(0, 31, 1)); bulletin.datadesc.push_back(WR_VAR(0, 7, 4)); bulletin.datadesc.push_back(WR_VAR(0, 8, 1)); bulletin.datadesc.push_back(WR_VAR(0, 10, 3)); bulletin.datadesc.push_back(WR_VAR(0, 11, 1)); bulletin.datadesc.push_back(WR_VAR(0, 11, 2)); if (!is_crex) { bulletin.datadesc.push_back(WR_VAR(2, 22, 0)); bulletin.datadesc.push_back(WR_VAR(1, 1, 0)); bulletin.datadesc.push_back(WR_VAR(0, 31, 2)); bulletin.datadesc.push_back(WR_VAR(0, 31, 31)); bulletin.datadesc.push_back(WR_VAR(0, 1, 31)); bulletin.datadesc.push_back(WR_VAR(0, 1, 32)); bulletin.datadesc.push_back(WR_VAR(1, 1, 0)); bulletin.datadesc.push_back(WR_VAR(0, 31, 2)); bulletin.datadesc.push_back(WR_VAR(0, 33, 7)); } bulletin.load_tables(); } virtual void to_subset(const Msg& msg, wreport::Subset& subset) { TempBase::to_subset(msg, subset); /* 0 */ add(WR_VAR(0, 1, 1), DBA_MSG_BLOCK); /* 1 */ add(WR_VAR(0, 1, 2), DBA_MSG_STATION); /* 2 */ add(WR_VAR(0, 2, 11), DBA_MSG_SONDE_TYPE); /* 3 */ add(WR_VAR(0, 2, 12), DBA_MSG_SONDE_METHOD); do_D01011(); do_D01012(); /* 9 */ add(WR_VAR(0, 5, 1), DBA_MSG_LATITUDE); /* 10 */ add(WR_VAR(0, 6, 1), DBA_MSG_LONGITUDE); /* 11 */ add(WR_VAR(0, 7, 1), DBA_MSG_HEIGHT_STATION); int rep_count_pos = subset.size(); subset.store_variable_undef(WR_VAR(0, 31, 1)); /* Iterate backwards as we need to add levels in decreasing pressure order */ int group_count = 0; for (int i = msg.data.size() - 1; i >= 0; --i) { msg::Context& c = *msg.data[i]; // We only want levels with a vertical sounding significance const Var* vss = c.find_vsig(); if (vss == NULL) continue; /* Add pressure */ if (const Var* var = c.find(WR_VAR(0, 10, 4))) subset.store_variable(WR_VAR(0, 7, 4), *var); else if (c.level.ltype1 == 100) subset.store_variable_d(WR_VAR(0, 7, 4), c.level.l1); else subset.store_variable_undef(WR_VAR(0, 7, 4)); /* Add vertical sounding significance */ { Var nvar(subset.tables->btable->query(WR_VAR(0, 8, 1)), (int)convert_BUFR08042_to_BUFR08001(vss->enqi())); nvar.setattrs(*vss); subset.store_variable(WR_VAR(0, 8, 1), nvar); } /* Add geopotential */ if (const Var* var = c.find(WR_VAR(0, 10, 3))) subset.store_variable(WR_VAR(0, 10, 3), *var); else if (const Var* var = c.find(WR_VAR(0, 10, 8))) subset.store_variable(WR_VAR(0, 10, 3), *var); else if (c.level.ltype1 == 102) subset.store_variable_d(WR_VAR(0, 10, 3), (double)c.level.l1 * 9.80665); else subset.store_variable_undef(WR_VAR(0, 10, 3)); /* Add wind direction */ if (const Var* var = c.find(WR_VAR(0, 11, 1))) subset.store_variable(WR_VAR(0, 11, 1), *var); else subset.store_variable_undef(WR_VAR(0, 11, 1)); /* Add wind speed */ if (const Var* var = c.find(WR_VAR(0, 11, 2))) subset.store_variable(WR_VAR(0, 11, 2), *var); else subset.store_variable_undef(WR_VAR(0, 11, 2)); ++group_count; } subset[rep_count_pos].seti(group_count); if (!is_crex) { int count = subset.append_dpb(WR_VAR(2, 22, 0), subset.size(), WR_VAR(0, 33, 7)); if (opts.centre != MISSING_INT) subset.store_variable_i(WR_VAR(0, 1, 31), opts.centre); else subset.store_variable_undef(WR_VAR(0, 1, 31)); if (opts.application != MISSING_INT) subset.store_variable_i(WR_VAR(0, 1, 32), opts.application); else subset.store_variable_undef(WR_VAR(0, 1, 32)); subset.store_variable_i(WR_VAR(0, 31, 2), count); } } }; } // anonymous namespace void register_temp(TemplateRegistry& r) { r.register_factory(2, "temp", "Temp (autodetect)", [](const Exporter::Options& opts, const Messages& msgs) { const Msg& msg = Msg::downcast(msgs[0]); // Get the type of equipment used if (const wreport::Var* var = msg.get(WR_VAR(0, 2, 3), Level(1), Trange::instant())) // Is it a Radar? if (var->enq(0) == 3) return unique_ptr